Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose a toWavBuffer function #46

Open
seofernando25 opened this issue Feb 1, 2024 · 1 comment · May be fixed by #47
Open

Expose a toWavBuffer function #46

seofernando25 opened this issue Feb 1, 2024 · 1 comment · May be fixed by #47

Comments

@seofernando25
Copy link

seofernando25 commented Feb 1, 2024

A server returning the contents from sam.buf8(...) doesn't automatically plays on the client.

It would be nice if there was a sam.toWavBuffer() function for this and similar use cases.

The code for it already exists in the RenderBuffer function found here, so an implementation of it could just be a refactor of that function:

const toWavBuffer = (audiobuffer: Uint8Array) => {
    // This function is basically a refactor of RenderBuffer

    const text2Uint8Array = (text: string) => {
        const buffer = new Uint8Array(text.length);
        text.split("").forEach((e, index) => {
            buffer[index] = e.charCodeAt(0);
        });
        return buffer;
    };

    // Calculate buffer size.
    const realbuffer = new Uint8Array(
            // ...
    );

    let pos = 0;
    const write = (buffer: Uint8Array) => {
        realbuffer.set(buffer, pos);
        pos += buffer.length;
    };

    //RIFF header
    write(text2Uint8Array("RIFF")); // chunkID
    write(Uint32ToUint8Array(audiobuffer.length + 12 + 16 + 8 - 8)); // ChunkSize
    write(text2Uint8Array("WAVE")); // riffType
    //format chunk
    write(text2Uint8Array("fmt "));
    write(Uint32ToUint8Array(16)); // ChunkSize
    write(Uint16ToUint8Array(1)); // wFormatTag - 1 = PCM
    write(Uint16ToUint8Array(1)); // channels
    write(Uint32ToUint8Array(22050)); // samplerate
    write(Uint32ToUint8Array(22050)); // bytes/second
    write(Uint16ToUint8Array(1)); // blockalign
    write(Uint16ToUint8Array(8)); // bits per sample
    //data chunk
    write(text2Uint8Array("data"));
    write(Uint32ToUint8Array(audiobuffer.length)); // buffer length
    write(audiobuffer);

    return realbuffer;
}

const DownloadBuffer = (audiobuffer: Uint8Array) => {
     const blob = new Blob([toWavBuffer(realbuffer)], { type: "audio/wav" });
     // Other code to download buffer
}

any thoughts on it? I understand if you do not want to expose that on the API for simplicity.

I would be more than glad to open a PR.


Also thank you so much for making this library 🙏

@discordier
Copy link
Owner

That would make sense... to be honest, I did not like having the download hack via the embedded <a> element in the same method as the wav blob generating for some time.

It makes totally sense to separate them, as not all wav buffers must get downloaded or, as in your case, even should get streamed verbatim to a client.

Current implementation simply assumed to be run in a browser and provide wav files to download.

Opening a PR would be nice, it will become 0.3.0 then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants