Hello, I'm a trying to make a piece of code to mix 2 WAV files and hear the output on my headphones. I've spent hours trying differents things with no success and now I feel I should ask for some light from experienced people :)
I've found explanations on how to mix audio streams on this page : http://www.vttoth.com/digimix.htm. But it doesn't really fits my own situation since samples I get with libsndfile are signed values. My piece of code works well for some files, but for others, it makes unpleasant clicks. I think I use a wrong algorithm, wich one do you use for such a situation ? Maybe I also use wrong data types, wich one should I use ? Is there any framework wich does such a task well ? I had a look at SndObj which seems to do such things but it's also quite old and not maintained against today configurations. Here is the guilty : #include <stdio.h> #include <ao/ao.h> #include <math.h> #include <fcntl.h> #include <string.h> #include <sys/types.h> #include <sndfile.h> #define BUFFER_SIZE 1024 #define DYNAMIC_RANGE 65535 int main( int argc, char **argv ) { /* variables pour libao */ ao_device * device; ao_sample_format format; int default_driver; /* variables pour libsndfile */ SNDFILE * wav1; SNDFILE * wav2; SF_INFO sfinfo; SF_INFO sfinfo2; /* float volumized */ static short buffer1 [BUFFER_SIZE]; static short buffer2 [BUFFER_SIZE]; static short mixed_buffer [BUFFER_SIZE]; int max_frames; int buffer_cpt; int number_of_buffers; int i; /* faut remplir la stucture sfinfo avec des z�ros */ memset (&sfinfo, 0, sizeof (sfinfo)) ; /* -- Initialize -- */ if(!(wav1 = sf_open(argv[1], SFM_READ, &sfinfo))) exit(0); if(!(wav2 = sf_open(argv[2], SFM_READ, &sfinfo2))) exit(0); ao_initialize(); /* -- Setup for default driver -- */ default_driver = ao_default_driver_id(); format.bits = 16; format.channels = sfinfo.channels; format.rate = sfinfo.samplerate; format.byte_format = AO_FMT_LITTLE; /* -- Open driver -- */ device = ao_open_live(default_driver, &format, NULL /* no options */); if (device == NULL) { fprintf(stderr, "Error opening device.\n"); } /* la duree de jeu est en fonction de la longueur * du plus long fichier */ if ( sfinfo.frames > sfinfo2.frames ) { max_frames = sfinfo.frames; } else { max_frames = sfinfo2.frames; } number_of_buffers = max_frames / BUFFER_SIZE * 2; for ( buffer_cpt = 0; buffer_cpt <= number_of_buffers; buffer_cpt++ ) { /* -- lecture depuis les fichiers -- */ sf_read_short (wav1, buffer1, BUFFER_SIZE); sf_read_short (wav2, buffer2, BUFFER_SIZE); /* -- mixage, cf. http://www.vttoth.com/digimix.htm -- */ for ( i = 0; i <= BUFFER_SIZE; i++ ) { mixed_buffer[i] = buffer1[i] + buffer2[i] - buffer1[i] * buffer2[i] / DYNAMIC_RANGE; } /* -- envoi dans la carte son -- */ ao_play(device, (char *) mixed_buffer, sizeof(mixed_buffer)); } ao_close(device); ao_shutdown(); exit(0); } /* EOF */ Thanks :-) -- Alex
