Left and Right audio channels are exchanging - c

I am trying to write an application for capturing stereo audio. My audio input has two channels(Stereo). I am writing this audio data into a wav file. Some times these audio channels are exchanging i.e, Left becomes right and right becomes left. This is happening only if i open and close the device file or turn off the device and turn it on. And it is happening randomly. I don't want channels to be exchanged. Please suggest.

stereo PCM stored in a wav file is in an LR format. 'L' stands for left channel sample and 'R' for right channel sample. I guess you have a bug in retrieving or storing the PCM. Maybe sometimes you start with the right (correct) position in buffer and sometimes you start with the second sample. It's hard to tell without additional info.

Related

Convert a stereo wav to mono in C

I have developed the Synchronous Audio Interface (SAI) driver for a proprietary Real-Time Operating System (RTOS) using C language. My driver is configured to output left and right channel data (I2S) to the amplifier. But, since the amplifier attached is mono, it only outputs left or right channel audio data to the speaker. Now, i have a stereo PCM 16-bit audio data file and i want to somehow mix the left and right channel audio data in my application and send it to either of the left or right channel in the SAI driver. In this way, i will be able to play combined stereo audio data as mono on the speaker attached to the mono amplifier.
Can anyone suggest me that what's the best possible solution to do it?
As said in a comment, the usual way to mix two stereo channels in a mono one is to divide the sample of each channel by 2 and add them.
Example in C like :
int left_channel_sample, right_channel_sample;
int mono_channel = (left_channel_sample / 2) + ( right_channel_sample / 2);
You mentioned some driver you coded, modify it or add some new feature. Can't really help more given the mess of your question...

FFmpeg: what does av_parser_parse2 do?

When sending h264 data for frame decoding, it seems like a common method is to first call av_parser_parse2 from the libav library on the raw data.
I looked for documentation but I couldn't find anything other than some example codes. Does it group up packets of data so that the resulting data starts out with NAL headers so it can be perceived a frame?
The following is a link to a sample code that uses av_parser_parse2:
https://github.com/DJI-Mobile-SDK-Tutorials/Android-VideoStreamDecodingSample/blob/master/android-videostreamdecodingsample/jni/dji_video_jni.c
I would appreciate if anyone could explain those library details to me or link me resources for better understanding.
Thank you.
It is like you guessed, av_parser_parse2() for H.264 consumes input data, looks for NAL start codes 0x000001 and checks the NAL unit type looking for frame starts and outputs the input data, but with a different framing.
That is it consumes the input data, ignores its framing by putting all consecutive data into a big buffer and then restores the framing from the H.264 byte stream alone, which is possible because of the start codes and the NAL unit types. It does not increase or decrease the amount of data given to it. If you get 30k out, you have put 30k in. But maybe you did it in little pieces of around 1500 bytes, the payload of the network packets you received.
Btw, when the function declaration is not documented well, it is a good idea to look at the implementation.
Just to recover the framing is not involved enough to call it parsing. But the H.264 parser in ffmpeg also gathers some more information from the H.264 stream, eg. whether it is interlaced, so it really deserves its name.
It however does not decode the image data of the H.264 stream.
DJI's video transmission does not guarantee the data in each packet belongs to a single video frame. Mostly a packet contains only part of the data needed for a single frame. It also does not guarantee that a packet contains data from one frame and not two consecutive frames.
Android's MediaCodec need to be queued with buffers, each holding the full data for a single frame.
This is where av_parser_parse2() comes in. It gathers packets until it can find enough data for a full frame. This frame is then sent to MediaCodec for decoding.

Changing the play back rate of a buffer in C?

I am using an Altera DE2 FPGA board and playing around with the SD card port and audio Line Out. I'm programming in VHDL and C, but the C portion is where I'm stuck due to lack of experience/knowledge.
Currently, I can play a .wav file from the SD card to the Line Out. I'm doing this by reading and sending the SD card data > FIFO > Audio Codec > Line Out. Ignoring all the other details, the code simply is:
UINT16 Tmp1=0;
...
Tmp1=(Buffer[i+1]<<8)|Buffer[i]; //loads the data from the SD card to Tmp1
//change the buffer rate?
IOWR(AUDIO_BASE, 0, Tmp1); //sends Tmp1 data to Line Out
If I were to print Tmp1, it's basically the points on a sine wave. What I want to do now is fiddle with how the sound plays by changing the play back rate (ideally I want to play the sound up or down an octave, which is just double or half the frequency). Can anyone provide some suggestions on how I can do this in the section:
//change the buffer rate?
Is it possible in C to write a few lines of code in that section to obtain what I'm looking for? ie. change how fast I'm reading from the Tmp1 buffer to the AUDIO_BASE.
Thanks in advance!
~Sarengo
If the IOWR interface provides no such option then you will have to do it yourself: You have to re-sample the sound. The theory can be found here 1 here 2 here 3 and here 4.
Raising the freqency by a multiple is easy: Just drop some samples, eg lower the freqency by factor 2 by just dropping every second sample from the buffer so that it then has half the size.
Lowering the frequency is harder because you need information you dont have: the samples in-between samples. You could start with simple linear interpolation and if you think that it does not sound good enough you can change it for something more advanced. Eg you can half the frequency by inserting a sample between two samples with their average value. If your waveform looks like this: 5 9 7 3 you would get 5 7 9 8 7 5 3

Jpeg wireless transfer with fwrite(); Need to handle lost packets

I am developing a device that takes a picture and transfers that picture to desktop computer receiver wirelessly through radio waves. On the receiver end, I am using C and fwrite() to rebuild the image file sent by split packets of data. Receiving a packet executes:
fwrite(&data[3], size, 1, filename);
data[3] is an unsigned 8 bit integer, data type u08.
I confirm that wired file transfer works. If the transmitter and receiver are directly connected, there is no problem.
However, the radio signal is not strong enough to guarantee that all packets will be received. In my testing, lost in transmission packets are common. If even one packet is lost, the image file becomes corrupt. Received rate is roughly 85%.
Every packet is numbered. If the received packet number is greater than the expected packet number, then the receiver knows that a packet has been dropped.
My solution is to loop and replace missing packets with a default packet while incrementing the expected packet number counter. Basically, I plan to fill lost pixels with black pixels, using the received packets to create the most completely picture possible. I do not know how to do this. I tried simply setting data[3] to 0 if the received packet number and expected packet number do not match up, but this did not work.
I welcome other proposed solutions.
U have not mentioned the image format. If you are sending crude RGB image then setting to zero thing should work but if you are playing with compressed images like jpeg and you have lost the header packets having information about block sizes or tables used for entropy encoding there is no way to get the image back.

How to multiplex Vorbis and Theora streams using libogg

I am currently writing a simple Theora video encoder, which uses libogg, libvorbis and libtheora. Currently, I can submit frames to the Theora encoder, and PCM samples to the Vorbis encoder, pass the resulting packets to Ogg streams (one for Theora and one for Vorbis) and get pages out.
When the program starts, it flushes the headers first from the Theora encoder, then from the Vorbis encoder to the output file (obviously, both streams have unique serial numbers). Then, I write interleaved pages to the file from both of the streams.
When writing just the video, or just the audio, I am able to play back the output in mplayer just fine, however when I attempt to write both, I get the following:
Ogg demuxer error : we met an unknown stream
I'm guessing I'm doing the multiplexing wrong. I have read through the documentation for multiplexing streams on Xiph.org, and I can't see where I differ. I cannot seem to find any example code for doing this, short of going through the source of an open-source encoder (which I'm having some trouble understanding). Would anyone be able to explain how to multiplex streams correctly using libogg? I'm trying to do this in C on Ubuntu 10.04, using the libraries from the Ubuntu repository.
Many thanks in advance!
Tom
Ok, for anyone who was reading this, I have to some extent solved it.
You should not flush all of the the header packets from each stream - just the first (setup) packet, which for Vorbis and Theora gets its own page by default. Put the other header packets into their respective streams, but do not flush until the setup pages from all streams have been written to the file.
Once you have done this, try to keep the streams as closely sync'd as possible (mplayer gave some errors for me when they got too far out). At 24fps video and 44.1 KHz audio, 1 frame should span 1837.5 audio samples (with PCM audio, this is 7,350 bytes).
If anyone else has any tips / info, it would be good to hear - I've never done anything with audio / video before!
Thanks!
Tom

Resources