* Create a stereo sound with alsa
@ 2012-07-28 8:26 Luca Longhi
2012-07-28 9:36 ` Clemens Ladisch
0 siblings, 1 reply; 2+ messages in thread
From: Luca Longhi @ 2012-07-28 8:26 UTC (permalink / raw)
To: alsa-devel
[-- Attachment #1: Type: text/plain, Size: 516 bytes --]
Hi. I've written a code to play two different sine wave (same amplitude and
f1=440Hz f2=600Hz) one on the left channel and the other on the right
channel. It seems to be working. I've tried doing the same thing using two
different sounds file (stereo) but the result is wrong. Obviously I've
played the sounds file separately and the result is correct. I think that
the problem is the configuration of the pcm. Could you give me some advice?
The code is attached. If you want I'll send you the sound files. Regards.
[-- Attachment #2: stereo.c --]
[-- Type: text/x-csrc, Size: 7289 bytes --]
#include <alsa/asoundlib.h>
#include <math.h>
#include <string.h>
void error(char * filename) {
perror(filename);
exit(0);
}
int main() {
int err;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int Fc, val;
int channels=2;
int size;
int dir=0;
unsigned int period_time;
unsigned int buffer_time;
snd_pcm_uframes_t frames;
int periodi=50;
snd_output_t *output = NULL;
/* Open PCM device for playback. */
err = snd_pcm_open(&handle, "default",SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {
fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(err));
exit(1);
}
snd_pcm_hw_params_alloca(¶ms);/* Allocate a hardware parameters object. */
err=snd_pcm_hw_params_any(handle, params);/* Fill it in with default values. */
if (err < 0) {
printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
return err;
}
err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);/* Interleaved mode */
//Interleaving means that we alternate samples for the left and right channel
if (err < 0) {
printf("Access type not available for playback: %s\n", snd_strerror(err));
return err;
}
err=snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); //16bit per campione=2byte per campione
if (err < 0) {
printf("Sample format not available for playback: %s\n", snd_strerror(err));
return err;
}
err = snd_pcm_hw_params_set_channels(handle, params, channels);/* Two channels (stereo) */
if (err < 0) {
printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err));
return err;
}
Fc = 44100;
err=snd_pcm_hw_params_set_rate_near(handle, params, &Fc, &dir);
if (err < 0) {
printf("Rate %iHz not available for playback: %s\n", Fc, snd_strerror(err));
return err;
}
period_time=143880;
err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir);
if (err < 0) {
printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
return err;
}
buffer_time=2*period_time;
err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir);
if (err < 0) {
printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
return err;
}
err = snd_pcm_hw_params(handle, params);/* Write the parameters to the driver */
if (err < 0) {
printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
return err;
}
err = snd_output_stdio_attach(&output, stdout, 0);//per vedere i valori finali dei parametri
if (err < 0) {
printf("Output failed: %s\n", snd_strerror(err));
return 0;
}
snd_pcm_hw_params_get_period_size(params, &frames, 0);
size = frames * 4; //riempio il buffer su piu periodi
//Un periodo è il numero di frames tra un interrupt. L'hardware viene interrotto "periodi" volte al buffer
/* 2 canali, 2byte per campione */
//buffer = (char *) malloc(size);
snd_pcm_hw_params_get_period_time(params, &val, &dir);//val=periodo (in micro secondi)
char * buffer1;
char * buffer2;
char * risultato;
FILE * fp1;
FILE * fp2;
long dimensione1;
long dimensione2;
long dim_finale;
unsigned int result;
if((fp1 = fopen("/home/luca/Tesi/un_suono_per_canale/stereo/sonar_smallroom_16.pcm", "r")) == NULL)
{printf("Impossibile aprire primo file\n"); return 1;}
else
{
fseek(fp1, 0, SEEK_END); // posiziona alla fine del file
dimensione1 = ftell(fp1); // legge la posizione attuale
rewind(fp1); // riavvolgi
fprintf(stderr, "size: %ld bytes\n", dimensione1);
buffer1 = (char*) malloc(sizeof(char) * dimensione1); //allocazione di memoria
if(buffer1 == NULL) perror("memory");
result = fread(buffer1, dimensione1, 1, fp1); // lettura file in memoria
if((fp2 = fopen("/home/luca/Tesi/un_suono_per_canale/stereo/dingstereo_16.pcm", "r")) == NULL)
{printf("Impossibile aprire secondo file\n"); return 1;}
else
{
fseek(fp2, 0, SEEK_END); // posiziona alla fine del file
dimensione2 = ftell(fp2); // legge la posizione attuale
rewind(fp2); // riavvolgi
fprintf(stderr, "size: %ld bytes\n", dimensione2);
buffer2 = (char*) malloc(sizeof(char) * dimensione2); //allocazione di memoria
if(buffer2 == NULL) perror("memory");
result = fread(buffer2, dimensione2, 1, fp2); // lettura file in memoria
if(dimensione1<dimensione2)
{
dim_finale=dimensione2;
}
if(dimensione2<=dimensione1)
{
dim_finale=dimensione1; //dimensione finale uguale alla dimensione del file piu grande
}
risultato = (char*) malloc(sizeof(char) * dim_finale); //allocazione di memoria
int j1=0;
int j2=1;
int i=0;
float v1;
float v2;
while(i<dim_finale)
{
if (j1<dimensione1)
{v1=buffer1[j1];} //prendo il canale sinistro del primo suono e lo scrivo sul canale sinistro
else
{v1=0;}
if (j2<dimensione2)
{v2=buffer2[j2];} //prendo il canale destro del secondo suono e lo scrivo sul canale destro
else
{v2=0;}
risultato[i++]=v1;
risultato[i++]=v2;
j1=j1+2;
j2=j2+2;
}
int n;
/*
n=0;
while(n<10)
{
snd_pcm_writei(handle, buffer2, dimensione2/4);
//dim_finale/4=n°di FRAME da scrivere (4=1 frame in byte=n°canali*n°byte per campione)
n++;
}
n=0;
while(n<10)
{
snd_pcm_writei(handle, buffer1, dimensione1/4);
//dim_finale/4=n°di FRAME da scrivere (4=1 frame in byte=n°canali*n°byte per campione)
n++;
}
*/
n=0;
while(n<10)
{
snd_pcm_writei(handle, risultato, dim_finale/4);
//dim_finale/4=n°di FRAME da scrivere (4=1 frame in byte=n°canali*n°byte per campione)
n++;
}
if (err == -EPIPE) {
/* EPIPE means underrun */
//Durante la riproduzione, se l'applicazione non passa i dati nel buffer abbastanza
//velocemente, praticamente si sente il suono a spezzoni, questo errore è chiamato underrun
fprintf(stderr, "underrun occurred\n");
snd_pcm_prepare(handle);//prepara la pcm per l'uso
} else if (err < 0) {
fprintf(stderr,
"error from writei: %s\n",
snd_strerror(err));
} else if (err != (int)frames) {
fprintf(stderr,
"short write, wrote %d frames\n", err);
}
snd_pcm_dump(handle, output);
snd_pcm_drain(handle);//per la riproduzione (Playback) attende la riproduzione di tutti i frame
//in sospeso e poi arresta la pcm
snd_pcm_close(handle);
//chiude il puntatore handle alla pcm e libera tutte le risorse ad esso associate
//free(buffer);//per deallocare la memoria allocata con malloc
}
}
fclose(fp1);
fclose(fp2);
free(buffer1);
free(buffer2);
free(risultato);
return 0;
}
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Create a stereo sound with alsa
2012-07-28 8:26 Create a stereo sound with alsa Luca Longhi
@ 2012-07-28 9:36 ` Clemens Ladisch
0 siblings, 0 replies; 2+ messages in thread
From: Clemens Ladisch @ 2012-07-28 9:36 UTC (permalink / raw)
To: Luca Longhi; +Cc: alsa-devel
Luca Longhi wrote:
> Hi. I've written a code to play two different sine wave (same amplitude and
> f1=440Hz f2=600Hz) one on the left channel and the other on the right
> channel. It seems to be working. I've tried doing the same thing using two
> different sounds file (stereo) but the result is wrong.
> err=snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); //16bit per campione=2byte per campione
> ...
> char * buffer1;
> char * buffer2;
> char * risultato;
> ...
> {v1=buffer1[j1];}
> {v2=buffer2[j2];}
> risultato[i++]=v1;
> risultato[i++]=v2;
The device expects 16-bit samples, but you write 8-bit values.
Regards,
Clemens
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-07-28 9:36 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-28 8:26 Create a stereo sound with alsa Luca Longhi
2012-07-28 9:36 ` Clemens Ladisch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).