[linux-audio-dev] [newbie] mixing audio streams

Alex Marandon al at alpage.org
Sat Mar 13 16:13:11 UTC 2004


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



More information about the Linux-audio-dev mailing list