0

To start learning to use asoundlib.h, I am writing a simple program that plays a tone. I am filling an array of shorts, samples of length buffersize. with samples of a sine wave.

When I pass samples to snd_pcm_writei() with its length, buffersize, the samples in samples are played for half of the time and noise is played for the other half of the time. When I pass samples to snd_pcm_writei() with a length of buffersize/2, the output is half as long clearly but all the noise is eliminated. That is to say, it seems like snd_pcm_writei() expects two array elements for each sample, but I cannot figure out why.

I am writing sample values to each element of samples. Believe I am configuring the pcm correctly for single channel, 16-bit, 44100 sample rate playback. I have it configured for one period per buffer.

Is there something in my pcm configuration that is causing snd_pcm_writei() to process twice as many array elements as I'm expecting it to? If not, what else could be causing half of whats played back to be noise?

Code below

#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
#include <math.h>
#include "waveform.h"

#define pi 3.14159265358979323846

int main() { int duration=10; //seconds int samplerate=44100; int periodsize=44100; int periodsperbuffer=1; //dont change for nodbay int buffersize=periodsizeperiodsperbuffer; int periodtime=(int)1000000(((double)periodsize)/(samplerate)); int iterations=(int)((double)duration*1000000/(periodtime));

short *samples;
samples = (short*)malloc(sizeof(short)*buffersize);
for (int i=0; i&lt;buffersize; i++) {
    samples[i]=0;
}


snd_pcm_t *pcm;
if (snd_pcm_open(&amp;pcm, &quot;hw:CARD=PCH,DEV=0&quot;, SND_PCM_STREAM_PLAYBACK,0)&lt;0) {
    printf(&quot;Couldn't open device for playback\n&quot;);
}
snd_pcm_hw_params_t *hw_params;

snd_pcm_hw_params_alloca(&amp;hw_params);
snd_pcm_hw_params_any(pcm, hw_params);
snd_pcm_hw_params_set_access(pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(pcm, hw_params, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(pcm, hw_params, 1);
snd_pcm_hw_params_set_rate(pcm, hw_params, samplerate, 0);
snd_pcm_hw_params_set_periods(pcm, hw_params, periodsperbuffer, 0);
snd_pcm_hw_params_set_period_time(pcm, hw_params, periodtime, 0);

snd_pcm_hw_params(pcm, hw_params);

float freq=440;
float phase=0;
float amp=1;
add_harmonic(samples,buffersize,freq,phase,amp,samplerate);

for (int i=0; i&lt;iterations; i++){
    snd_pcm_writei(pcm, samples, buffersize/2); // why does buffersize need to
}                                               // be divided by two??

snd_pcm_drain(pcm);
snd_pcm_close(pcm);

free(samples);

return 0;

}

and the function add_harmonic from waveform.h

void add_harmonic(short *buffer, int bufferlen, float freq, float phase, float amp, int samplerate) {
    freq=freq*2*pi;
    phase=phase*2*pi;
    int max=0;
    for (int i=0; i<bufferlen; i++) {
        buffer[i] = buffer[i]+(short)amp*sin(freq*(float)i/samplerate+phase)*10000;
        if (buffer[i]>max) {
            max=buffer[i];
        }
    }
    for (int i=0; i<bufferlen; i++) {
        buffer[i] = (short)(10000*buffer[i]/max);
    }
}

Side note, the program sometimes segfaults even when the size of the buffer is specified as buffersize/2.

0 Answers0