I'm writing a program in C which should visualize audio. As audio source I use a microphone and the Alsa C Sound library. I take the sound frames from the Alsa library, make some transformations (Fourier analysis and similar), and then visualise them. I almost have a working program besides one exception, it seems I'm converting the Alsa-frames to doubles in a wrong way.
This is how I do it:
unsigned char x=getFirstByte();
signed char y=getSecondByte();
double analog_signal=(y*256+x)/32768.;
Now this code works, but sometimes (relatively often) I get spikes where the value of analog_signal is about 0.99... where it shouldn't be.
So I started printing the values of x and y when such spikes occur.
The output was quite clear: always when such a spike occurred y was equal to 127 and x was some value around 230.
My conversion is still correct in my understanding, but it seems that Alsa treats its values in a different way. So that this special value of 127 in the second byte has to be converted differently, for whatever reason?!
I don't want to believe that my microphone is broken, so could someone who has worked with the Alsa-library, kindly give me some advice on my problem.
I would also be happy with a function of the Alsa-library which does this conversion for me as I haven't found one but maybe overlooked it.
Related
Currently, I am trying to read the volume / gain of a raw 16 bit PCM audio stream. Basically, I'd like to be able to pipe a stream into an executable and print a number in a range from 0 (no sound) to 1 (at volume limit / 0db from clipping) followed by a new line. This should continue only when manually cancelled or when the audio source exits. It does not need to be very acurate, nor do the values require being smoothed heavily (like an RMS value; although a bit of smoothing would probably be better than none at all). The problem is that I understand very little of how to work with raw PCM, and when I found the math, I realized that I currently do not posses the skills required to do something like this. So my question would be: Could someone who's more familiar with the matter provide me with a working example code that could do the behaviour described above, idealy with an explaination of what exactly is done?
The language isn't too important, although something fast like Rust, C, C++, etc. would be preferred.
being part of a lab course, I have to update the simulation about Pulse Coded Modulation. Initially, the simulation was written in 1998 using the OSS (open sound system) and was never updated thereafter. I have rewritten the entire code and ported it to ALSA.
The code itself is a bit long, that's why I haven't put it here but am providing a link.
Now to my issue: Whenever I want to play a vector of random length containing many samples, I start hearing weird periodic random noises. I have a feeling it's due to a buffer underrun. For a better understanding, I have recorded the output.
I believe it has to do something with the parameters I've set. Even though I tried out many cases, I didn't come to a solution.
Just take a look at the period size, buffer size, periods and the sbplay(..) function. PS.: My HW is set such that buffer size = period size * periods
I hope you can help me somehow! Thanks in advance
Code
Output WAV
BTW.: ALSA: buffer underrun on snd_pcm_writei call
didn't help me much...
Efe,
Why don't you try the audioplayer/audiorecorder functions in MATLAB. They use ALSO on Linux. If you want greater control over the latency try the dsp.AudioPlayer/AudioRecorder system objects.
Dinesh
I'm trying to send a converted temperature reading from my DS1820 to my PC using a PIC16F877 uart. I am using MPLABX and the XC8 compiler, which has a build in usart.h, though it's only useful for the PIC18 series, so I'm using usart_pic16.h which has been written to work with the PIC16 series by a third party.
I am successfully collecting the temperature in its hex form from the DS1820 and have converted it to a human readable float, but I can't find a way to forward the float value to the PC via the UART.
The usart_pic16.h library allows for direct sending of chars, strings, lines and ints over the usart using the following methods:-
void USARTWriteChar(char ch);
void USARTWriteString(const char *str);
void USARTWriteLine(const char *str);
void USARTWriteInt(int16_t val, int8_t field_length);
I'm stuck at finding a way to send the float value across the uart using this library, which includes extraction and sending a decimal point.
I did try sending a string like this:-
USARTWriteString( "TempC= %7.3f degrees C \r\n", temp_c );
Where temp_c is the float value of the temp, but it errorred with "too many function arguments" while compiling. Probably obvious to those c gurus out there, which I'm unfortunately not :(
Maybe one way would be to extract each value from the float and sent it as an int, with the exception of the decimal point which could probably be found with an 'if' check of each value, then when the decimal point is found just send it as a char e.g. USARTWriteChar('.');, which does work. Unfortunately I don't know how to extract individual float values or if it's the best way to do it.
I wasn't sure if my code was required to solve this so thought I'd avoid spamming it unless someone asks.
Any help would be great.
Thanks.
The general equivalent would be to include <stdio.h> and do something like the following:
char s[64];
sprintf(s, "TempC= %7.3f degrees C \r\n", temp_c);
USARTWriteString(s);
Although for an embedded platform you may be best to avoid the printf style functions that can use a fair bit of code space on a small microcontroller. Also in the above example it would make sense to break just the floating point conversion into a seperate sprintf and output the rest of the string seperately so the buffer s doesn't have to be so large.
That should get you running for the moment but in the longer term you might want to look at converting the temperature to integer say by multiplying it by 1000 and then decoding the value on the PC, that's assuming eventually you intend to write your own application to communicate with the microcontroller.
I've done some searching and have not found anything that would boost the file and formatting functions in Visual Studio VS2010 C (not C++).
I've been able to address the raw i/o issues to some extent by using large buffers and a SSD drive, so the more pressing issue is a replacement for the family of printf functions.
Has anyone found something worthwhile?
As I understand it, part of the glacial speed issue with the printf functions is that they have to handle myriad types of arguments. Does anyone have experience with writing a datatype-specific version of printf; eg, one that only prints ints, or only prints doubles, etc?
First off, you should profile the code first before assuming it's printf.
But if you're sure it's printf and similar then you can do a few things to fix the issue.
1) print less. IE, don't call expensive operations as much if you can avoid it. Do you need all the output, for example?
2) manually replace the string concatenation with manually built routines that do all the pieces without having to parse the format specifier.
EG: printf("--%s--", "really cool");
Can become:
write(1, "--", 2);
write(1, "really cool", 11);
write(1, "--", 2);
That may be faster. But again, you won't know until you profile it. Don't spend energy on a solution till you can confirm it's the solution you need and be able to measure the success of your proposed solution.
#Wes is right, never assume you know what you need to fix until you have proof.
Where I differ is on the method of finding out.
I and others use random pausing which works for these reasons, and here's a short slide show demo & C++ code so you can see how it works, if you want.
The thing about printf (or any output) function is it spends A) a certain number of CPU cycles creating a buffer to be output, and then it spends B) a certain amount of time waiting while the system and/or auxiliary hardware actually moves the data out.
That's maybe a bit over-simplified, but if you randomly pause and examine the state, that's what you see.
What you've done by using large buffers and an SSD drive is reduce B, and that's good.
That means of the time remaining, A is a larger fraction.
You know that.
Now of the samples you find in A, you might get a hint of what's happening if you see what subordinate routines inside printf are showing up.
Usually printf calls something like vprintf to get rid of the variable argument list, which then cycles over the format string to figure out what to do, including things like parsing precision specifiers.
If it looks like that's what it's doing, then you know about how much time goes into parsing the format.
On the other hand, if you see it inside a routine that is copying a string, or formatting an integer (along with dealing with leading/trailing characters, etc.) then you know to concentrate on that.
On yet another hand, if you see it inside a routine that looks like it's formatting a floating point number (which is actually quite complicated), you know to concentrate on that.
Given all that, you want to know what I do?
First, I ask who is going to read this anyway?
If nobody really needs to read all this text, why not pump it out in binary? Or failing that, in hex?
If you simply write binary, A shrinks to nothing, and when you read it back in with another program, guess what?
No Lost Bits!
i have a two audio files one is original file and another i have corrupted it by reversing some bits, how to compare the quality of these two files is there any algorithm or an software where i can compare the quality of the two files.
"any algorithm or an software": Do you want to program or not?
If you want a software to do this for you: stackoverflow cannot help you
If you are willing to program (at least call functions in a library) that's a different story:
There are some libraries which can do this, specifically to convert the audio from compressed to WAVEFORM format in the first place (the library-to-choose depends on which format your audio is in). Or is your audio in waveform format already? you didnt tell. If you have the audio in waveform format (raw audio in e.g. * signed 16bit mono at 22khz) you can easily program this yourself: Since the only damage you did to your audio is bitflips you can iterate throught them and just sum the differences up: you have to take in account the format the waveform is in tho: you cannot compare the bit-level (because each bit has different significance); if you have * signed 16bit audio you have to use in C the type int so that A) the comparison is signed and B) the difference does not overflow.
One physical measurement for the quality of sound is the SNR: http://en.wikipedia.org/wiki/Signal-to-noise_ratio. I don't know of any lib that does that for you, but it is not to hard to do yourself:
calculate the noise: noise[n] = manipulated[n] - original[n], n = sample index
calculate the power of "noise" and of "original": p_noise[n] = noise[n] * noise[n], ...
get the SNR by dividing the values = SNR[n] = p_original[n]/p_noise[n]
You may want to calculate an average(!) SNR... I hope you can figure out how to do that yourself. This should put your on the right track.