[LAD] mixing while using libao and libsndfile

David Griffith dave at 661.org
Sun May 15 16:34:34 UTC 2016


I've been knocking my head against a wall for more than a year trying to 
figure out how to correctly mix two streams of audio while using 
libsndfile for input and libao for output.  My main requirement is that I 
cannot assume anything about the output drivers -- that is, I cannot 
depend on the output driver (ALSA, OSS, Sun, etc) being able to do the 
mixing for me.  Many of my target platforms lack any sort of mixing 
services.  I need to do this myself.  I tried starting a mixer/player 
thread that would work in a producer/consumer relationship with one or two 
audio file decoder threads.  I can play one sound at a time just fine. 
When I try to do both, I get distortion followed by a segfault.

So, I'm back to a demo program.  What must I do to this program to cause 
it to start playing one audio file, then play another N seconds later?

David Griffith
dave at 661.org

===begin code===
/*
  * gcc -o mixer mixer.c -lao -lsndfile
  *
  */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ao/ao.h>
#include <sndfile.h>

#define BUFFSIZE 512

int playfile(FILE *);

int main(int argc, char *argv[])
{
 	FILE *fp1, *fp2;

 	if (argc < 2) {
 		printf("usage: %s <filename>.ogg <filename>.aiff\n", argv[0]);
 		exit(1);
 	}
 	fp1 = fopen(argv[1], "rb");
 	if (fp1 == NULL)  {
 		printf("Cannot open %s.\n", argv[1]);
 		exit(2);
 	}
 	fp2 = fopen(argv[1], "rb");
 	if (fp2 == NULL)  {
 		printf("Cannot open %s.\n", argv[1]);
 		exit(3);
 	}

 	ao_initialize();
 	playfile(fp1);
 	playfile(fp2);
 	ao_shutdown();

 	return 0;
}

int playfile(FILE *fp)
{
 	int default_driver;
 	ao_device *device;
 	ao_sample_format format;
 	SNDFILE *sndfile;
 	SF_INFO sf_info;
 	short *shortbuffer;
 	int64_t toread;
 	int64_t frames_read;
 	int64_t count;

 	sndfile = sf_open_fd(fileno(fp), SFM_READ, &sf_info, 1);
 	memset(&format, 0, sizeof(ao_sample_format));
 	shortbuffer = malloc(BUFFSIZE * sf_info.channels * sizeof(short));
 	frames_read = 0;
 	toread = sf_info.frames * sf_info.channels;
 	count = 0;

 	default_driver = ao_default_driver_id();
 	memset(&format, 0, sizeof(ao_sample_format));

 	format.byte_format = AO_FMT_NATIVE;
 	format.bits = 16;
 	format.channels = sf_info.channels;
 	format.rate = sf_info.samplerate;

 	device = ao_open_live(default_driver, &format, NULL);
 	if (device == NULL) {
 		printf("Error opening sound device.\n");
 		exit(4);
 	}
 	while (count < toread) {
 		frames_read = sf_read_short(sndfile, shortbuffer, BUFFSIZE);
 		count += frames_read;
 		ao_play(device, (char *)shortbuffer, frames_read * sizeof(short));
 	}
 	ao_close(device);
 	sf_close(sndfile);
}
===end code===

-- 
David Griffith
dave at 661.org


More information about the Linux-audio-dev mailing list