rochars / wavefile Goto Github PK
View Code? Open in Web Editor NEWCreate, read and write wav files according to the specs. :star: :notes: :heart:
License: MIT License
Create, read and write wav files according to the specs. :star: :notes: :heart:
License: MIT License
Hello!
I have only a link to file on remote server. How can I make WaveFile from browser?
var WaveFile = new WaveFile('./trueWav.wav');
console.log(wav.chunkSize);
returns Uncaught Error: Not a supported format.
How can I make a buffer from it in browser?
Thank you :)
I am unable to convert a LINEAR16 .wav file to an alaw wav file due to an error stating I am using an unsupported file type
I'm trying to receive the sound (buffer) recording from a web (javascript) with socket.io in the server and then create the wav file using your library.
There is no error but when the created wav file is reproduced (VLC), it is like static or illegible sounds
scriptNode.onaudioprocess = function (audioEvent) {
if (recording) {
input = audioEvent.inputBuffer.getChannelData(0);
// convert float audio data to 16-bit PCM
var buffer = new ArrayBuffer(input.length * 2)
var output = new DataView(buffer);
for (var i = 0, offset = 0; i < input.length; i++, offset += 2) {
var s = Math.max(-1, Math.min(1, input[i]));
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
}
socketio.emit('write-audio', buffer);
}
}
//just initialize an uuid
@SocketIoEvent(eventName = "start-recording")
this.startRecording = async (message, currentSocket, globalSocket) => {
console.log(message);
currentSocket["current_wav_id"] = uuidv4();
}
//join the chunks/buffer into one
@SocketIoEvent(eventName = "write-audio")
this.writeAudo = async (message, currentSocket, globalSocket) => {
console.log(message);
console.log(currentSocket["current_wav_id"])
if(typeof buffers[currentSocket["current_wav_id"]] === 'undefined'){
buffers[currentSocket["current_wav_id"]] = message;
}else{
var newBuffer = Buffer.concat([buffers[currentSocket["current_wav_id"]], message]);
buffers[currentSocket["current_wav_id"]] = newBuffer;
}
}
//save the buffer as wav file
@SocketIoEvent(eventName = "end-recording")
this.endRecording = async (message, currentSocket, globalSocket) => {
console.log(message);
console.log(currentSocket["current_wav_id"])
console.log(buffers[currentSocket["current_wav_id"]]);
var wav = new WaveFile();
wav.fromScratch(1, 44100, '16', buffers[currentSocket["current_wav_id"]]);
fs.promises.writeFile(`/tmp/sandbox/${currentSocket["current_wav_id"]}.wav`, wav.toBuffer());
}
The html client is sending a valid waf file because it works with python: the write-audio event is received perfectly and the wav is created
Html client
The html client is this https://github.com/miguelgrinberg/socketio-examples/blob/8281e127cf0d2228e793594527d7d19e8138a62e/audio/static/audio/main.js#L145C42-L145C48
server
I will try to create a Minimal, Reproducible Example.
Thanks in advance
Hello, and thanks for this library! I'm trying to use it to convert audio coming in from Twilio so it can be transcribed by Amazon Transcribe. Unfortunately, I'm getting back empty responses from AWS (ex: { TranscriptEvent: { Transcript: { Results: [] } } }). Here's the transform stream I'm using for the conversion.
new stream.Transform({
transform(chunk, encoding, done) {
const wav = new WaveFile();
wav.fromScratch(1, 8000, '8m', Buffer.from(chunk, 'base64'));
wav.fromMuLaw();
this.push(Buffer.from(wav.data.samples));
done();
}
});
The audio from Twilio is mulaw encoded. AWS has this on their best practices webpage for supported audio "PCM (only signed 16-bit little-endian audio formats, which does not include WAV)". I'm assuming that's exactly what I get when running wav.fromMuLaw(), correct? Should I try using wav.getSamples(false, Int16Array) instead of wav.data.samples? Any other things I should try?
Thanks for your help.
Hi,
first of thanks for creating this <3! I was wondering if it would be possible to add support to write/update the bwf bext chunk of a wav file. I tried changing the values in .bext but it's not written back to the file. I've checked with bwf meta edit, a tool to edit bwf meta data.
Thanks,
Michael
I'm just working on something that generates peaks for wave files which I read the data from via base64, and to match what I have I'd prefer the buffer to output in 16 bit, possibly signed format?
Is there a way to do this with what
This would be my ideal:
const waveFile = new WaveFile();
waveFile.fromDataURI(waveFileBase64);
const audioFileBuffer = waveFile.toBuffer('16');
Or can I just convert this to 16 bit?
Many thanks
You got a couple of ways to load wav files...
and also exporting them:
Base64 isn't a good container cuz it takes up way more space, a Uint8Array is way better.
<audio src="">
element then it's better to create a Object URL from a blobencourage base64 today isn't so good.
it's better to just have one way to solve it so that less code can be shipped and bundled.
also don't know how i feel about the name toBuffer
and fromBuffer
the name mostly implies that it is dealing with NodeJS buffers. how about to/fromUint8array ?
true ESM requires path to be explicit in order to find them. remote path resolver like http import isn't so good at locating this extension-less paths cuz it can't scan the dir if you meant ./foo/index.js
or ./foo.js
this would allow to run the code without having to even compile it first.
I can't find any source stating that mu-law should require an extensible fmt header to to include the validbitspersample. including this in the header breaks several players, including windows media player and groove music. ffmpeg and soundforge do not put this extensible header in.
Is there some reason why it should be there?
Importing WaveFile like so: import WaveFile from "wavefile"
and attempting to create an instance like: const reader = new WaveFile()
results in the following error: TypeError: wavefile_1.default is not a constructor
.
However, importing like: const wavefile = require("wavefile")
works fine, but then TypeScript type checking stops working.
Hi,
In REAPER, is seems that there is two type of elements marked by CUE points, markers, and regions.
It seems that wavefile is only able to get marker and region start, not region end.
PS: note that pointes are simply named with an index, contrary to what I can see in REAPER. But this is surely another issue.
Thanks again for this library !
WAV with RIFF chunks like:
is read by wavefile with a funky signature like:
{
"chunkId": "RIFF",
"chunkSize": 639470,
"format": "WAVE",
"subChunks": [
{
"chunkId": "fmt ",
"chunkSize": 16,
"chunkData": {
"start": 20,
"end": 36
}
},
{
"chunkId": "data",
"chunkSize": 639096,
"chunkData": {
"start": 44,
"end": 639140
}
},
{
"chunkId": "LIST",
"chunkSize": 68,
"format": "INFO",
"subChunks": [
{
"chunkId": "INAM",
"chunkSize": 14,
"chunkData": {
"start": 639160,
"end": 639174
}
},
{
"chunkId": "ISFT",
"chunkSize": 34,
"chunkData": {
"start": 639182,
"end": 639216
}
},
{
"chunkId": "cue ",
"chunkSize": 76,
"chunkData": {
"start": 639224,
"end": 639300
}
},
{
"chunkId": "LIST",
"chunkSize": 102,
"format": "adtl",
"subChunks": [
{
"chunkId": "ltxt",
"chunkSize": 20,
"chunkData": {
"start": 639320,
"end": 639340
}
},
{
"chunkId": "labl",
"chunkSize": 16,
"chunkData": {
"start": 639348,
"end": 639364
}
},
{
"chunkId": "labl",
"chunkSize": 16,
"chunkData": {
"start": 639372,
"end": 639388
}
},
{
"chunkId": "labl",
"chunkSize": 14,
"chunkData": {
"start": 639396,
"end": 639410
}
},
{
"chunkId": "smpl",
"chunkSize": 60,
"chunkData": {
"start": 639418,
"end": 639478
}
}
]
},
{
"chunkId": "smpl",
"chunkSize": 60,
"chunkData": {
"start": 639418,
"end": 639478
}
}
]
},
{
"chunkId": "cue ",
"chunkSize": 76,
"chunkData": {
"start": 639224,
"end": 639300
}
},
{
"chunkId": "LIST",
"chunkSize": 102,
"format": "adtl",
"subChunks": [
{
"chunkId": "ltxt",
"chunkSize": 20,
"chunkData": {
"start": 639320,
"end": 639340
}
},
{
"chunkId": "labl",
"chunkSize": 16,
"chunkData": {
"start": 639348,
"end": 639364
}
},
{
"chunkId": "labl",
"chunkSize": 16,
"chunkData": {
"start": 639372,
"end": 639388
}
},
{
"chunkId": "labl",
"chunkSize": 14,
"chunkData": {
"start": 639396,
"end": 639410
}
},
{
"chunkId": "smpl",
"chunkSize": 60,
"chunkData": {
"start": 639418,
"end": 639478
}
}
]
},
{
"chunkId": "smpl",
"chunkSize": 60,
"chunkData": {
"start": 639418,
"end": 639478
}
}
]
}
This causes an exception where wavefile makes one LIST type (INFO or adtl) a subchunk of the other LIST type.
Hello, I work in public radio here in the US, and we use 2 additional standards on top of BWF, with wav files containing MPEG data chunks, and also a cart chunk which gives additional information for broadcast scheduling and automation systems.
MPEG support (compression code 80, mext chunk, and extensions to fmt)
https://tech.ebu.ch/docs/tech/tech3285s1.pdf
Cart Chunk
http://www.aes.org/publications/standards/search.cfm?docID=41
(I have purchased the spec, but b/c of rights and licensing I will not post it)
http://www.cartchunk.org/cc_spec.htm (most of the spec is here)
I'm interested in adding support for these, would you be open to such additions to your project?
Happy to work on some PRs for these.
FWIW - I have experience implementing support for these in Ruby, https://github.com/kookster/nu_wav, and I've used that gem to parse and create such wav files in production systems, but rather than port that to js, I'd rather enhance and support your high quality work on wav files.
Hey @rochars I just noticed you pushed a commit a few days ago, and I hope it means you are ok.
If there is anything I can do to help, with this project or whatever I can do, please let me know.
I think the recent updates didn't have to be major version updates. It seems like there aren't any breaking api changes but just bug fixes and added functionality. So this could have been done with minor and patch versions. See the semver spec for information on what version number to increment when: https://semver.org
It would be nice to also document the releases in something like a changelog: https://keepachangelog.com/en/1.0.0, so people know what changed.
How can wavefile be used to change this?
This is currently an important topic for speech recognition as data is often recorded as stereo, but needs to be submitted for recognition as mono.
Thanks!
Thanks for the great tool. I am using it to read the selected wave file before uploading it.
It works well in Chrome but not in Firefox and Safari. Following is the code snippet.
const wav = new WaveFile();
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function() {
wav.fromDataURI(reader.result);
//...
}
Upon checking, I found that the container
value is a blank string in Firefox while 'RIFF' in Chrome.
this.container = this.readString(buffer, 4);
if (this.supported_containers.indexOf(this.container) === -1) {
throw Error('Not a supported format.');
}
PS - I hope you are safe and healthy in these crazy times.
Thanks for creating this useful tool.
One use-case I need is to read/verify smpl
Sample Chunks via command line:
https://sites.google.com/site/musicgapi/technical-documents/wav-file-format#smpl
Your tool has the funcationality to parse the smpl
chunks but does not make them available by the CLI.
Hi! Today, I made a fresh fork of wavefile and then executed...
git clone [email protected]:erikh2000/wavefile.git
cd wavefile
npm install
npm run build
The build fails with several error messages along these lines (can post the full spiel, if you like):
../../node_modules/@types/jest/index.d.ts:458:62 - error TS1005: ']' expected.
458 type NonFunctionPropertyNames<T> = keyof { [K in keyof T as T[K] extends Func ? never : K]: T[K] };
../../node_modules/@types/jest/index.d.ts:458:65 - error TS1005: ';' expected.
458 type NonFunctionPropertyNames<T> = keyof { [K in keyof T as T[K] extends Func ? never : K]: T[K] };
~
../../node_modules/@types/jest/index.d.ts:458:70 - error TS1005: ';' expected.
458 type NonFunctionPropertyNames<T> = keyof { [K in keyof T as T[K] extends Func ? never : K]: T[K] };
~~~~~~~
../../node_modules/@types/jest/index.d.ts:458:94 - error TS1005: ';' expected.
458 type NonFunctionPropertyNames<T> = keyof { [K in keyof T as T[K] extends Func ? never : K]: T[K] };
~
../../node_modules/@types/jest/index.d.ts:458:95 - error TS1128: Declaration or statement expected.
458 type NonFunctionPropertyNames<T> = keyof { [K in keyof T as T[K] extends Func ? never : K]: T[K] };
This output is coming more specifically from executing the tsc ./test/TypeScript/index.ts
command in the test-tsc
package.json script:
No preceding commands, e.g. rollup -c
, are outputting failure messages.
I promise I didn't change anything in my fork. Any ideas on how to fix? Maybe there is an uncommitted file on somebody's local directory, e.g. tsconfig.json
? Or a global NPM package that is relied upon? Or I'm building with the wrong version of node or npm?
how to convert wave file to alaw using python?
please help converting a wave file to alaw file using python!
This is how currently getSamples()
is defined in index.d.ts
getSamples(interleaved?:boolean, OutputObject?: Function): Float64Array;
It is supposed to return a Float64Array. But, according to the docs, when there are more than 2 channels, it returns an array of Float64Arrays.
If the file is stereo or have more than one channel then the samples will be returned de-interleaved in a Array of Float64Array objects, one Float64Array for each channel.
This creates confusion when you try to create some logic around it, for example, if you need to go through all channels, you might write something like this:
const numChannels = (wave.fmt as any).numChannels;
let sampleChannels: Float64Array[] = [];
if (numChannels > 1) {
sampleChannels = wave.getSamples() as Float64Array[];
}
else {
sampleChannels.push(wave.getSamples() as Float64Array);
}
Unfortunately, this fails. I had to change the return type in index.d.ts to: Float64Array | Float64Array[]
.
I think this would be the right declaration and should be changed, or the function could be changed so that it always returns an array of arrays.
This is a feature request or enhancement, but I'm wondering if it is possible for wavefile to recognize cue markers that have both a start AND end point—markers like this can be created in Adobe Audition, for example. Note the "start" and "end" times in this screenshot:
And here is a link to the file that the screenshot was taken with:
https://www.dropbox.com/transfer/AAAAACWjc7db0I3xtIeZ8l9CdhEH-kgKOCyCfrkJFS1nwrv-vYQ3Nu8
Would love to know your thoughts on if this is possible.
I have a WAVE file with cue points. One of them has the label "Marker 01 abcäöüß". Yet when I call listCuePoints()
, the corresponding label string is "Marker 01 abcä�ö�ü�ß�".
The reason for this is that the method WaveFile.readZSTR_
tries to convert the string byte by byte, which gives wrong results for multi-byte UTF-8 code points.
I found an easy fix. Given that this project is currently unmaintained, I'm not opening a PR. Instead, here's a small snippet of code that patches the bug at runtime:
const WaveFile = require('wavefile');
const { unpackString } = require('byte-data');
WaveFile.prototype.readZSTR_ = function patchedReadZSTR_(bytes, start = 0) {
let end = start;
while (end < bytes.length && bytes[end]) end++;
return unpackString(bytes, start, end);
}
I am using an API that streams chunks of audio as they become available. I need to send this to Twilio which only accepts mulaw encoded base64. Is there a way to convert each chunk individually to mulaw bas64 or must it be done only when the full file is received?
private class methods have been supported for quite some time now in all modern versions.
using real private #
helps minifiers/bundlers to create even smaller files
It seems that samples
does not exist as documented in the readme:
// array of numbers
console.log(wav.samples);
instead, it's available under samples_
, and the unit tests seem to only test for the samples_
property as well. Is this an oversight? Should samples not be available under samples
and not samples_
?
wav file from telephony system recorded using 8 bit mono, 8000Hz, u-law, The voicemail plays fine in VLC and other media player. When decode it using fromIMAADPCM(), static noise, choppy playback got introduced.
When running command line for bit depth: the wav file returns 505
Any suggestions on fixing it?
Hi,
I finally found this library. I was looking for something like it for a long time. But sadly it appears to have pretty strong limitations (or I have not found the documentation for my problem):
In my scenario, I want to use the library to update the CUE points within a node.js local processed script. The files I am editing are podcasts that are 1 hour long - thus the WAV files tend to be around 500MB. The library seems to only handle smaller files (I am getting the JavaScript heap out of memory
with the big file, but not with a 1-minute file that's only 15MB in size).
So my question is two-fold:
I'd really love to be able to use this lib. It's an amazing project and it would be a lifesaver for me. Sadly right now I can't really make much use of it.
Looking forward to working with WaveFile!
Chris
P.S.: I also tried setting the node --max-old-space-size=8192
to ridiculously high values. Nothing worked.
Hi I use this in my react native project. When I try to load wav file from data no matter base64 or a buffer, I always got error that byteData_ is an empty so things like byteData_.types is undefined. I had to change all other byteData_ to byteData in file except the definition one here. I also had to do the same thing for riffChunks_. Can someone help me with this? I don't quite get why byteData without the underscore has all the information. Thanks
I wanna merge multiple Wav files to one, can I use this library to handle this?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.