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(a)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(a)661.org
Show replies by thread