I am currently implementing a central raspberry pi 3B that collects acoustic noise data from another device which has a mic via BLE. I am currently using node.js, noble to retreive the data. Currently the sound information is 8-bits which is sampled at 8kHz. I was wondering if its possible to use p5 to record this audio stream data using the stream of input sound information rather than that of the mic of the computer as specified in the library for the function audioIn.
Is there any way around this?
Your project has many pieces. Break it down into small pieces and check bit by bit. Yo have
- R-PI 3
- External ADC streaming your mic data
- P5.js sound to capture this data
The first step is to see if p5.sound can connect to this device and access this data. Have you done any test so far?
Hi kfrajer, thank you for your response!
So far I have implemented the first 4 blocks you have mentioned where the raspberry pi 3 is able to receive the stream of audio data from the external device via BLE using a node.js script. Where the data received is in the format of an array of size 20. Thus I am on the final part of the problem, using p5.js sound to capture and record this received stream of audio data.
Looking through the p5.sound library there is a function for mic = p5.audioIn; where it requests the browsers mic. Instead I would like the audio input to be from the stream of data I receive from the BLE device.
I was wondering if there is a way to route the stream of audio data as audioIn or if there is a similar method to be able to record this data using p5 sound.
Thank you !
You want to use p5.js because you are using node, right? You want to use p5.js sound as you want to save your data using a sound file format, right?
Not sure if p5.js can do it:
You will be limited by the Sound API, which defines your input sources. A couple of options is to save the file as raw binary and convert it manually in a second step. As an alternative, I believe you could use Minim and Processing java. Now, I don’t think I have tried this before but I think it would be possible. For this, there is a need to “roll-up one’s sleeves” to get it done.
In case you are wondering if you can mix node and Processing Java, the answer is sort of yes. You run Processing from node using
exec(), so you are executing a Processing sketch in the background. There are some other ideas following this approach. For this, it is important to know more about your project. Do you want to play the sound as it arrives or is it enough to store it and save it as shown in the P5.sound’s recorder example? In this example, the data is transfer to another class (stored in memory) as saved at the end.
Before you follow this rabbit-hole, maybe do a quick search to see if there is a js library available that could do this for you or even if there is a program with a CLI interface that will convert your raw data into a sound file.
Yes I was wanting to use p5 since I was using node.js as I thought it would be an easier alternative.
Since I want to just record the sound and store it, I will attempt storing the stream of data in a txt.file and converting it to a sound file at a later stage.
Thank you very much for your input!
I am not sure if I am allowed to ask this question here but since you gave me the great idea, here goes;
I have attempted to stream the data I am receiving by concatenating each of the data arrays I am receiving via BLE to a new array dataBuffer. The dataBuffer is then written into a text file after a set interval of 20 seconds, as seen in the uploaded image. Since the data is being sampled at 8kHz when there is an interval of 20 seconds I am expecting around 160,000 samples, but I am only storing 7620 in the text file.
My question is, can node.js keep up with the concatenating speed of the dataBuffer array to store all of the data in that variable or is this method not a viable one as the speed of the incoming data is relatively fast?
I can only suggest to break your problem down.
Create a small code that generates high kHz data and save it. Try different js libs.
Then use it in node.
Then share in the forum if you want to
I would like to share how I (almost) finished my project to you and maybe to others attempting a similar project.
The sound data I was receiving from (the ThunderboardSense) had two main problems.
- The data was VOX ADPCM encoded
- The data sent was in packets of 224 bytes where I was only receiving 20bytes at a time causing me to lose out on 204 bytes every packet. Hence the slow speed.
To overcome problem 2 I sent out data from the thunderboard sense at 20 bytes per packet instead and the number of samples improved.
I had streamed the data into a text file after storing all the values and appending the data to an array for a set time interval. Since the data in the txt file was still an VOX ADPCM encoded message I needed to decode it. (I had used an encoded compressed form to send data because for the set baud rate of the thunderboard sense of 115200 I am unable to send 16kHz samples at 8-bits but VOX ADPCM encoding enables me to do so).
To decode the audio message from the .txt file to a satisfactory level, I did the following:
- Used Matlab to format the text file so it has one row and an ‘x’ amount of columns, where ‘x’ represents the number of samples.
- Used Matlab to convert the array created from the text file to a WAV file using half the sampling rate of the mic. (Since VOX ADPCM encodes 2 bytes of audio as 1 byte)
- Used Audacity to convert the WAV file to an unsigned 8-Bit .RAW Audio file
- Used Audacity to convert the .Raw Audio to a WAV file using their inbuilt VOX ADPCM decoder in the software at the original sample rate of the mic.
That was it, I was able to create a mic that operates via Bluetooth low Energy with the ability to record the data. Although the sound quality is not crystal clear, the sound is still audible
Thank you again Kf, your insight on how to go about this aspect of the project is much appreciated.