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

Closed
seofernando25 opened this issue Feb 1, 2024 · 1 comment · Fixed by #47
Closed

Expose a toWavBuffer function #46

seofernando25 opened this issue Feb 1, 2024 · 1 comment · 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.

discordier added a commit that referenced this issue Jun 11, 2024
Feature release 0.3.0

Features:
- New method `SamJs.wav(text: string, phonetic?: boolean): Uint8Array;`
which
  renders a wave buffer.
  See #46, #47 (thanks to @seofernando25)

Fixes:
- Typo `dipthong` has been corrected to `diphthong` all over the code
base.
This includes the flag `FLAG_DIPTHONG` which is now named
`FLAG_DIPHTHONG`.
  Fixes #19
- Fix comments to clearify that the '*' is not a wildcard but a marker
that the
  second char in a phoneme is to be ignored.
  Fixes # 21

Additionally minor changes like adding download in demo html file.
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