Programmer-RD-AI
feat: add Paragraph component and types for typography
a8aec61
raw
history blame
2.03 kB
export function decodeBase64Audio(
base64String: string,
mimeType = 'audio/mpeg',
sampleRate = 44100,
numChannels = 1
): string {
// Convert the Base64 string to binary
const byteString = atob(base64String)
const byteArray = new Uint8Array(byteString.length)
for (let i = 0; i < byteString.length; i += 1) {
byteArray[i] = byteString.charCodeAt(i)
}
let blob: Blob
if (mimeType === 'audio/pcm16') {
// Convert PCM16 raw audio to WAV format
const wavHeader = createWavHeader(byteArray.length, sampleRate, numChannels)
const wavData = new Uint8Array(wavHeader.length + byteArray.length)
wavData.set(wavHeader, 0)
wavData.set(byteArray, wavHeader.length)
blob = new Blob([wavData], { type: 'audio/wav' }) // Convert PCM to WAV
} else {
blob = new Blob([byteArray], { type: mimeType })
}
return URL.createObjectURL(blob)
}
// Function to generate WAV header for PCM16
function createWavHeader(
dataLength: number,
sampleRate: number,
numChannels: number
): Uint8Array {
const header = new ArrayBuffer(44)
const view = new DataView(header)
const blockAlign = numChannels * 2 // 16-bit PCM = 2 bytes per sample
const byteRate = sampleRate * blockAlign
// "RIFF" chunk descriptor
view.setUint32(0, 0x52494646, false) // "RIFF"
view.setUint32(4, 36 + dataLength, true) // File size
view.setUint32(8, 0x57415645, false) // "WAVE"
// "fmt " sub-chunk
view.setUint32(12, 0x666d7420, false) // "fmt "
view.setUint32(16, 16, true) // Subchunk1 size
view.setUint16(20, 1, true) // Audio format (1 = PCM)
view.setUint16(22, numChannels, true) // Number of channels
view.setUint32(24, sampleRate, true) // Sample rate
view.setUint32(28, byteRate, true) // Byte rate
view.setUint16(32, blockAlign, true) // Block align
view.setUint16(34, 16, true) // Bits per sample (16-bit)
// "data" sub-chunk
view.setUint32(36, 0x64617461, false) // "data"
view.setUint32(40, dataLength, true) // Data size
return new Uint8Array(header)
}