I’m writing an audio app in React Native that plays WAV file from local storage.
I was looking for a simple and little module to get the duration of WAV files, but I didn’t find nothing that I really like, so I started to study how the WAV file header is formatted.
(image from Soundfile)
How to read file in React Native to Buffer
In React Native we cannot use the NodeJS standard “fs” standard module, so I installed react-native-fs (https://github.com/itinance/react-native-fs).
With this library we can open the first 40 byte of the WAV file and serialize its data in Buffer to be able to get the fields we need to determine how long is the song.
We need:
- Chunk Size (from byte 4 to 8)
- Sample Rate (from byte 24 to 28)
- Num Channels (from byte 22 to 24)
- Bit per Sample (from byte 34 to 38)
and the duration is simple as ->
Chunk Size / (Sample Rate * Num Channels * (Bit per Sample / 8))
React Native has not support for Buffer natively, so you have to install it (npm install –save buffer) and import it as it shown below
global.Buffer = global.Buffer || require(‘buffer’).Buffer;
export const getWavDuration = (file) => { let buffer = new Buffer(40); RNFS.read(RNFS.MainBundlePath + "/" + file, 40, 0, 'ascii') .then(result => { //DATA BYTES //////////////////////////////////// //chunk_size 5-6-7-8 //sample_rate 25-26-27-28 //num_channel 23-24 //bit_per_sample 35-36-37-38 buffer = Buffer.from(result, 'ascii').toString('hex').match(/.{1,2}/g); const chunk_size = parseInt(buffer.slice(4, 8).reverse().join(""), 16); const sample_rate = parseInt(buffer.slice(24, 28).reverse().join(""), 16); const num_channel = parseInt(buffer.slice(22, 24).reverse().join(""), 16); const bit_per_sample = parseInt(buffer.slice(34, 38).reverse().join(""), 16); const duration = parseInt(chunk_size / (sample_rate * num_channel * (bit_per_sample / 8))); }); };
The buffer array is reversed because the data chunks are little endian 🙂
Credits
The icons in the featured image are under copyright.
Leave a Comment