alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* 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(&params);/* 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).