Re: [LAD] need help mixing on the fly

2017-02-19 Thread David Griffith

On Sun, 19 Feb 2017, David Griffith wrote:

I have created a test game to be loaded by Frotz for testing audio 
development.


Oops.  I forgot to add an URL to the test game: 
http://661.org/soundtest2.blb



--
David Griffith
d...@661.org

A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/listinfo/linux-audio-dev


Re: [LAD] need help mixing on the fly

2017-02-19 Thread David Griffith

On Sat, 18 Feb 2017, Fons Adriaensen wrote:


On Sat, Feb 18, 2017 at 01:44:32AM +, David Griffith wrote:


For a couple years I've been trying, without success, to reliably
mix two audio streams on the fly in C.  I'm using libao, libmodplug,
libsamplerate, libsndfile, and libvorbis.  The program is Frotz
(https://github.com/DavidGriffith/frotz), a Z-machine emulator for
playing old Infocom games as well as newer ones.  Could I please get
some help with this?


Mixing audio from two audio streams just requires adding the streams
sample by sample. I'm pretty sure that the real problem here is not
mixing but something else. But with the limited info you provide we
can only guess.

Where are the streams coming from ? What are the formats ? Where is
the result supposed to go ? etc. etc. etc.


The audio comes from AIFF, OGGV, and MOD files which are embedded in an 
IFF container file which also contains game data.  Using libmodplug, 
libsamplerate, libsndfile, and libvorbis; these audio chunks are turned 
into stereo streams of floats.  There are only two streams.  If two 
streams are active, mixing is done.  The resulting single stream of floats 
is converted to pcm16 and fed into libao for output.


The two streams are either "music" or "bleep".  The music stream can be 
fed with audio data from an OGGV chunk or MOD chunk, but not both.  The 
bleep stream is fed from an AIFF chunk.  If a new stream of the same type 
is started, the new one immediately takes over the old one.  This works. 
If both types are played at once, they're supposed to be mixed.  That 
process doesn't go right and I don't know where or why, though I suspect 
trouble with threads, mutexes, and/or semaphores.  The problem manifests 
in distorted sound and usually a segfault.


More detail...

A mixer thread is spawned when Frotz starts up.  It waits for one or both 
float buffers to fill whereupon it mixes their contents, converts the 
result to pcm16 and calls libao to play it.  playaiff() or playmusic() are 
spawned by the main thread as separate threads to read audio data from the 
container IFF and fill up the float buffers for the mixer to read.


The defective code is in 
https://github.com/DavidGriffith/frotz/blob/ao-curses/src/curses/ux_audio.c


I have created a test game to be loaded by Frotz for testing audio 
development.  It's at http://661.org/soundtest2.blb.  The game is a text 
adventure that simulates a single room which contains a Commodore 64, a 
Commodore Amiga, and a small box with buttons on it.  Turning on the C64 
causes an OGGV file to play.  The Amiga plays a MOD file.  The 
buttons on the small box cause AIFFs to play.  To tickle the bug, turn on 
one of the computers and then press a button on the box.


I'm not interested in using SDL or Pulseaudio for this project.


--
David Griffith
d...@661.org

A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/listinfo/linux-audio-dev


[LAD] need help mixing on the fly

2017-02-17 Thread David Griffith


For a couple years I've been trying, without success, to reliably mix two 
audio streams on the fly in C.  I'm using libao, libmodplug, 
libsamplerate, libsndfile, and libvorbis.  The program is Frotz 
(https://github.com/DavidGriffith/frotz), a Z-machine emulator for playing 
old Infocom games as well as newer ones.  Could I please get some help 
with this?



--
David Griffith
d...@661.org
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/listinfo/linux-audio-dev


Re: [LAD] mixing while using libao and libsndfile

2016-05-17 Thread David Griffith

On Tue, 17 May 2016, Andrea Del Signore wrote:


On Tue, May 17, 2016 at 12:25 AM, David Griffith <d...@661.org> wrote:
On Mon, 16 May 2016, Andrea Del Signore wrote:

> I'm not simply trying to mix two files.  My main project is a
> game engine in which two sounds are allowed at any one time. 
> For instance, there can be constant background music punctuated
> by sound effects.  I can't get these to mix correctly.

Hi,

in that case you can just skip the right number of frames before starting
playing sounds.

I modified my code to take the start time for each file and schedule the
play time with frame accuracy.

http://pastebin.com/0PMyfPvK

If you want your timing to be sample accurate the algorithm is a bit more
complex.


That won't work.  Your code schedules things ahead of time before anything 
else happens.  I need to be able to fire off sound effects the instant the 
player does something to cause them.  I can't know in advance.


--
David Griffith
d...@661.org___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/listinfo/linux-audio-dev


Re: [LAD] mixing while using libao and libsndfile

2016-05-16 Thread David Griffith
On May 16, 2016 3:25:48 PM PDT, David Griffith <d...@661.org> wrote:

>  Earlier you set up filebuffer like this:
>
>buflen = BUFFSIZE * sf_info[0].channels;
>filebuffer = malloc(buflen * sizeof(float));
>
>The size of filebuffer is BUFFSIZE float-sized frames.  Therefore when
>you 
>specify BUFFSIZE as the number of floats to read, they all fit in 
>filebuffer.

Sorry.  I meant BUFFSIZE as the number of /frames/.
-- 
David Griffith
d...@661.org
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/listinfo/linux-audio-dev


Re: [LAD] mixing while using libao and libsndfile

2016-05-16 Thread David Griffith

On Mon, 16 May 2016, Andrea Del Signore wrote:


> 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.

Hi,

not sure if I understood correctly: do you just want to mix N files?

Like you I'm learning libsndfile and libao so this is my attempt to mix some 
audio files:

http://pastebin.com/dm7z8b3Z

HTH,
Andrea

P.S.
Can someone explain line 88 (I already read the sndfile FAQ)?


I'm not simply trying to mix two files.  My main project is a game engine 
in which two sounds are allowed at any one time.  For instance, there can 
be constant background music punctuated by sound effects.  I can't get 
these to mix correctly.


Regarding your line 88, I had trouble with this too:

sf_count_t item_read = sf_read_float (sndfile[i], filebuffer, BUFFSIZE); 
// WHY BUFFSIZE? Shouldn't be BUFFSIZE * channels?


The third parameter is for the number of items or frames.  A frame is made 
up of one sample per channel.  Earlier you set up filebuffer like this:


buflen = BUFFSIZE * sf_info[0].channels;
filebuffer = malloc(buflen * sizeof(float));

The size of filebuffer is BUFFSIZE float-sized frames.  Therefore when you 
specify BUFFSIZE as the number of floats to read, they all fit in 
filebuffer.



--
David Griffith
d...@661.org___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/listinfo/linux-audio-dev


[LAD] mixing while using libao and libsndfile

2016-05-15 Thread David Griffith


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
d...@661.org

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

#include 
#include 
#include 
#include 
#include 
#include 

#define BUFFSIZE 512

int playfile(FILE *);

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

if (argc < 2) {
printf("usage: %s .ogg .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, _info, 1);
memset(, 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(, 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, , 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
d...@661.org
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/listinfo/linux-audio-dev