Play Raw File Using NAudio Library - audio

Hello i have following code to play raw file.my raw file duration is 25 second. this code is working fine but after sometime my program play raw file very slow almost 50% speed and my raw file duration is increase 36 second when i restart my pc and run my program its working normaly again. i need to restart my pc every one hour to work correctly please check what is wrong with my code here is my code
Try
Dim rawStream = File.OpenRead("C:\myFile.raw")
Dim waveFormat = New NAudio.Wave.WaveFormat(8000, 16, 1)
Dim rawSource = New RawSourceWaveStream(rawStream, waveFormat)
Dim audioBufferSize = 320
Dim offset As Integer = 0
Dim buffer As Byte() = New Byte(audioBufferSize - 1) {}
Dim buffer2 As Byte() = New Byte(320) {}
While (rawSource.Read(buffer2, offset, audioBufferSize) > 0)
msport.Write(buffer2, offset, audioBufferSize)
Thread.Sleep(20)
End While
Catch ex As Exception
MsgBox(ex.ToString)
End Try

NAudio is not having any effect at all in your code sample. All you are doing is reading data from a file, and sending it to the serial port. RawSourceWaveStream simply attaches a WaveFormat to the file stream, but nothing is reading that stream. Whatever device you have listening to the audio data you're sending over the serial port will have an audio format it is expecting. You need to find out what that is. Then you can use NAudio to convert the audio to the correct format if it is not already at the right sample rate / channel count (which would be the two most likely causes of audio playing at 50% speed)

Related

Speech to Text: Google API Error 400 Sync input too long. For audio longer than 1 min use LongRunningRecognize with a 'uri' parameter

I am still having trouble with transcribing a long audio file despite using gcs_uri link as described in the documentation. This is my code:
def googleAPI(self, gcs_uri):
client=speech.SpeechClient(credentials=CREDENTIALS)
audio = speech.RecognitionAudio(uri=gcs_uri)
config = speech.RecognitionConfig(
encoding=speech.RecognitionConfig.AudioEncoding.LINEAR16,
sample_rate_hertz=int(self.audio_frame),
language_code="fr-FR",
audio_channel_count=int(self.audio_channels),
enable_separate_recognition_per_channel=True,
use_enhanced=True,
model="phone_call",
)
#ADDED HERE FOR LONG AUDIO FILES
operation = client.long_running_recognize(config=config, audio=audio)
print("Waiting for operation to complete...")
response = operation.result(timeout=10000) #set timeout to a large number
response= client.recognize(config=config, audio=audio)
return response
My audio files are about 30-40 minutes long. Please advise.

convert audio file to Linear PCM 16-bit

I am trying to send an audio file through a websocket, and I realised that in order to do so i need to convert the mp3 file to a Linear PCM 16-bit code, but i cant find a way to do so.
here is what i want to do:
let mp3File = // the 16-bit pcm file
ws.on('message', async(msg) => {
if (typeof msg === "string") {
} else if (recognizeStream) {
recognizeStream.write(msg);
}
ws.send(mp3File) <== stream back the audio file
});
});
some background, the stream is a phone call (via vonage api) so ny ws connected to phone call and hear the user input, and then after some logic on my server i want to play to the user a mp3 file that is a local file in my server, via ws.send().
-----------update--------
now, if i send the pcm data from the stream (the raw audio from phone call)
its works (the server echoing the phone call )
so i want to convert the mp3 file to the same format so i could send it to via ws.send().
-----------update 2--------
after making my audio file at the right format which is:
" Linear PCM 16-bit, with either a 8kHz or a 16kHz sample rate, and a 20ms frame size "
i am trying to send the file trough the web socket but i dont know how to do so,
i have the file in the project folder but i dont know how to send it via websocket , i looked for how to do so but i dident find anything.
i am trying to do what specified here:
First let's understand what this means:
Linear PCM 16-bit, with either a 8kHz or a 16kHz sample rate, and a
20ms frame size
They are talking about 2 things here:
The format of audio data, which is "Linear PCM 16-bit, with either a 8kHz or a 16kHz sample rate"
How you send this audio data to them and how they send it to you: in chunks of audio data worth 20ms frames
Based on the audio format, if you choose "16bit Linear PCM with sample rate of 16K" implies:
samplerate = 16000
samplewidth = 16 bits = 2 byte
So an audio chunk of 1 second will contain bytes = (16000 * 2) = 32000 bytes
this means a 20ms/0.02s frame of audio will be equivalent to (32000*0.2) = 640 bytes
There are 2 things needed:
convert mp3 to wav. Install ffmpeg on your system and run this command
ffmpeg -i filename.mp3 -ar 16000 -sample_fmt s16 output.wav
This converts your filename.mp3 to output.wav which will be Linear PCM 16-bit in 16K samplerate
In your code, when you send audio back, you need to stream it as chunks of 640 bytes, not the entire file data in one shot. There are 3 options:
run a loop to write write all the audio to the websocket but in chunks of 640 bytes.
but this has an issue, Nexmo will buffer only first 20s of audio. Anything more than that will be discarded
start an async task that runs every 20ms and writes 640 bytes of data to websocket.
write when you get audio from nexmo (this is the one I will show)
Since nexmo will send you 640 bytes every 20ms, you can just send back 640 bytes at same time.
I'm writing this example using npm websocket package.
var fs = require('fs');
var binaryData = fs.readFileSync('output.wav');
var start = 44 // discard the wav header
var chunkSize = 640
...
// ws is a websocket connection object
connection.on('message', function(message) {
if (message.type === 'utf8') {
// handle a text message here
}
else if (message.type === 'binary') {
// print length of audio sent by nexmo. will be 640 for 16K and 320 for 8K
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
if (start >= binaryData.length) {
// slice a chunk and send
toSend = binaryData.slice(start, start + chunkSize)
start = start + chunkSize
connection.sendBytes(toSend);
console.log('Sent Binary Message of ' + toSend.length + ' bytes');
}
} ...
});
Remember, there will be some delay from the point you send the audio from your server to nexmo, and you hearing on other side.
It can vary from half a second to even more depending on the location of Nexmo's datacentre, of the server where you run your code, network speed etc.
I have observed it to be close to 0.5 sec.

Storing Value in Arduino Sent From Python via Serial

I have been trying to send a value from a Python program via serial to an Arduino, but I have been unable to get the Arduino to store and echo back the value to Python. My code seems to match that I've found in examples online, but for whatever reason, it's not working.
I am using Python 3.5 on Windows 10 with an Arduino Uno. Any help would be appreciated.
Arduino code:
void readFromPython() {
if (Serial.available() > 0) {
incomingIntegrationTime = Serial.parseInt();
// Collect the incoming integer from PySerial
integration_time = incomingIntegrationTime;
Serial.print("X");
Serial.print("The integration time is now ");
// read the incoming integer from Python:
// Set the integration time to what you just collected IF it is not a zero
Serial.println(integration_time);
Serial.print("\n");
integration_time=min(incomingIntegrationTime,2147483648);
// Ensure the integration time isn't outside the range of integers
integration_time=max(incomingIntegrationTime, 1);
// Ensure the integration time isn't outside the range of integers
}
}
void loop() {
readFromPython();
// Check for incoming data from PySerial
delay(1);
// Pause the program for 1 millisecond
}
Python code:
(Note this is used with a PyQt button, but any value could be typed in instead of self.IntegrationTimeInputTextbox.text() and the value is still not receieved and echoed back by Arduino).
def SetIntegrationTime(self):
def main():
# global startMarker, endMarker
#This sets the com port in PySerial to the port with the Genuino as the variable arduino_ports
arduino_ports = [
p.device
for p in serial.tools.list_ports.comports()
if 'Genuino' in p.description
]
#Set the proper baud rate for your spectrometer
baud = 115200
#This prints out the port that was found with the Genuino on it
ports = list(serial.tools.list_ports.comports())
for p in ports:
print ('Device is connected to: ', p)
# --------------------------- Error Handling ---------------------------
#Tell the user if no Genuino was found
if not arduino_ports:
raise IOError("No Arduino found")
#Tell the user if multiple Genuinos were found
if len(arduino_ports) > 1:
warnings.warn('Multiple Arduinos found - using the first')
# ---------------------------- Error Handling ---------------------------
#=====================================
spectrometer = serial.Serial(arduino_ports[0], baud)
integrationTimeSend = self.IntegrationTimeInputTextbox.text()
print("test value is", integrationTimeSend.encode())
spectrometer.write(integrationTimeSend.encode())
for i in range(10): #Repeat the following 10 times
startMarker = "X"
xDecoded = "qq"
xEncoded = "qq"
while xDecoded != startMarker: #Wait for the start marker (X))
xEncoded = spectrometer.read() #Read the spectrometer until 'startMarker' is found so the right amound of data is read every time
xDecoded = xEncoded.decode("UTF-8");
print(xDecoded);
line = spectrometer.readline()
lineDecoded = line.decode("UTF-8")
print(lineDecoded)
#=====================================
spectrometer.close()
#===========================================
#WaitForArduinoData()
main()
First, this is a problem:
incomingValue = Serial.read();
Because read() returns the first byte of incoming serial data reference. On the Arduino the int is a signed 16-bit integer, so reading only one byte of it with a Serial.read() is going to give you unintended results.
Also, don't put writes in between checking if data is available and actual reading:
if (Serial.available() > 0) {
Serial.print("X"); // Print your startmarker
Serial.print("The value is now ");
incomingValue = Serial.read(); // Collect the incoming value from
That is bad. Instead do your read immediately as this example shows:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
That's two big issues there. Take care of those and let's take a look at it after those fundamental issues are corrected.
PART 2
Once those are corrected, the next thing to do is determine which side of the serial communication is faulty. Generally what I like to do is determine one side is sending properly by having its output show up in a terminal emulator. I like TeraTerm for this.
Set your python code to send only and see if your sent values show up properly in a terminal emulator. Once that is working and you have confidence in it, you can attend to the Arduino side.

Raw audio playback in Allegro 5

I'm writing a MOD player, trying to playback a sample using Allegro5 raw stream capabilities, I can't figure out the exact init parameters for the stream to play the loaded sample data from the mod file.
This is what I have:
xf::ModLoader ml;
ml.loadFromFile("C:\\Users\\bubu\\Downloads\\agress.mod");
// getSampleLength() returns # of data words
int sample_length = ml.getSampleLength(1) * 2;
const int8_t* sample_data = ml.getSampleData(1);
ALLEGRO_MIXER* mixer = al_get_default_mixer();
ALLEGRO_AUDIO_STREAM* stream = al_create_audio_stream(1, sample_length, 8363, ALLEGRO_AUDIO_DEPTH_INT8, ALLEGRO_CHANNEL_CONF_1);
al_attach_audio_stream_to_mixer(stream, mixer);
al_set_audio_stream_gain(stream, 0.7f);
al_set_audio_stream_playmode(stream, ALLEGRO_PLAYMODE_ONCE);
al_set_audio_stream_playing(stream, true);
al_set_audio_stream_fragment(stream, (void*)sample_data);
al_drain_audio_stream(stream);
First of all, freq param is hardcoded for the test (8363Hz), but, playing back at the specified frequency I don't get what I expect, and al_drain_audio_stream() gets stuck forever playing garbage in a loop...
Any help would be appreciated.
At the very least, you need to be calling al_get_audio_stream_fragment before you call al_set_audio_stream_fragment. Typically you'd feed these streams in a while loop, while responding to the ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT event. See the ex_saw example in the Allegro's source for some sample code: https://github.com/liballeg/allegro5/blob/master/examples/ex_saw.c

NAudio - WaveOut doesn't raise PlaybackStopped event when used with WaveOffsetStream

When you create a WaveOut object, and initialize it with WaveOffsetStream, the PlaybackStopped event is not raised at the end of the playback. Code:
WaveOut myWaveOut = new WaveOut();
myWaveOut.PlaybackStopped += OnPlaybackStopped;
WaveOffsetStream OffsetStream = new WaveOffsetStream(MyOtherStream);
myWaveOut.Init(OffsetStream);
myWaveOut.Play();
WaveOutOffsetStream always returns the requested number of bytes from Read so it is a never-ending stream. You'd have to use something different, or detect when the Position went past the point you wanted to play to

Resources