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