0
0

I want to use subsounds for something I’m trying and I hit a wall. To try to understand them, I took the realtime stitching example and changed it a little.

The test app below tries to generate two tones (using PCMREADCALLBACK as in the user-generated sound example) and then play them alternating via the subsound double-buffer method under a parent sound.

Here’s the oddity; I can create the two tones and play them and hear them; or, I can load a pair of .ogg tones and play them and hear them.

But when I try to subsound them, only the LOADED subsounds will play, not the test tones (but they are there, I test-play them individually first).

I’m concerned that perhaps synthesized sounds can’t serve as subsounds (or at least if they are created as in the user-generated sound example). My next step is to simply pre-create the tones in a static buffer and see.

However, the code is attached below should anyone have any thoughts. There is a #if with a comment in the middle that can swap between generated and loaded sounds.

Thanks in advance,
Bill

[code:3s2gg8dt]#include <windows.h>

include <stdio.h>

include <conio.h>

include <math.h>

include "../../api/inc/fmod.hpp"

include "../../api/inc/fmod_errors.h"

typedef unsigned int uint;

void ERRCHECK(FMOD_RESULT result) {
if (result == FMOD_OK) return;
printf( "error (%d) %s\n", result, FMOD_ErrorString(result));
getch();
exit(-1);
}

// Generate tone A
FMOD_RESULT F_CALLBACK pcmreadcallback_A( FMOD_SOUND *sound, void *data, uint datalen ) {

static float t = 0;
short* ptr = (short*)data;
for (uint i=0; i &lt; datalen/2; i++) {  // 16-bit mono
    *ptr++ = (short)( sin(t) * 32767.0F );
    t += 0.05F;
}
return FMOD_OK;

}

// Generate tone B
FMOD_RESULT F_CALLBACK pcmreadcallback_B( FMOD_SOUND *sound, void *data, uint datalen ) {

static float t = 0;
short* ptr = (short*)data;
for (uint i=0; i &lt; datalen/2; i++) {  // 16-bit mono
    *ptr++ = (short)( sin(t) * 32767.0F );
    t += 0.1F;
}
return FMOD_OK;

}

int main( int argc, char *argv[] ) {

FMOD::System     *system;
FMOD::Sound      *sound;
FMOD::Sound      *subsound[2];
FMOD_CREATESOUNDEXINFO exinfo;
FMOD::Channel    *channel = 0;
FMOD_RESULT       result;

result = FMOD::System_Create(&amp;system);
ERRCHECK(result);

result = system-&gt;init( 1, FMOD_INIT_NORMAL, 0 );
ERRCHECK(result);

// Create parent stream
memset( &amp;exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO) );
exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
exinfo.defaultfrequency = 44100;
exinfo.numsubsounds     = 2;
exinfo.numchannels      = 1;
exinfo.format           = FMOD_SOUND_FORMAT_PCM16;
result = system-&gt;createStream( 0, FMOD_LOOP_NORMAL | FMOD_OPENUSER, &amp;exinfo, &amp;sound );
ERRCHECK(result);

if 1 // Use "#if 0" to load tones instead of create them

// Create tones
FMOD_CREATESOUNDEXINFO  createsoundexinfo_A;
memset( &amp;createsoundexinfo_A, 0, sizeof(FMOD_CREATESOUNDEXINFO) );
createsoundexinfo_A.cbsize            = sizeof(FMOD_CREATESOUNDEXINFO);           
createsoundexinfo_A.decodebuffersize  = 44100;                                      
createsoundexinfo_A.length            = 44100 * sizeof(short);
createsoundexinfo_A.numchannels       = 1;
createsoundexinfo_A.defaultfrequency  = 44100;
createsoundexinfo_A.format            = FMOD_SOUND_FORMAT_PCM16;
createsoundexinfo_A.pcmreadcallback   = pcmreadcallback_A;

// B's exinfo is the same as A except for the callback
FMOD_CREATESOUNDEXINFO createsoundexinfo_B = createsoundexinfo_A;
createsoundexinfo_B.pcmreadcallback = pcmreadcallback_B;

// Create the two tones as the subsounds
int mode = FMOD_OPENUSER | FMOD_LOOP_NORMAL | FMOD_CREATESTREAM;
result = system-&gt;createSound( 0, mode, &amp;createsoundexinfo_A, &amp;subsound[0] );
ERRCHECK(result);

result = system-&gt;createSound( 0, mode, &amp;createsoundexinfo_B, &amp;subsound[1] );
ERRCHECK(result);

else

// Use this block to LOAD, not CREATE tones
result = system-&gt;createStream(&quot;../media/e.ogg&quot;, FMOD_DEFAULT, 0, &amp;subsound[0]);
ERRCHECK(result);

result = system-&gt;createStream(&quot;../media/c.ogg&quot;, FMOD_DEFAULT, 0, &amp;subsound[1]);
ERRCHECK(result);

endif

// Set up subsounds
result = sound-&gt;setSubSound( 0, subsound[0] );
ERRCHECK(result);

result = sound-&gt;setSubSound( 1, subsound[1] );
ERRCHECK(result);

int soundlist[2] = { 0, 1 };
result = sound-&gt;setSubSoundSentence( soundlist, 2 );
ERRCHECK(result);

// Test the tones
printf( &quot;play tone 1...\n&quot; );
system-&gt;playSound( FMOD_CHANNEL_FREE, subsound[0], false, &amp;channel );
Sleep( 500 );
channel-&gt;stop();

printf( &quot;play tone 2...\n&quot; );
system-&gt;playSound( FMOD_CHANNEL_FREE, subsound[1], false, &amp;channel );
Sleep( 500 );
channel-&gt;stop();

// Play them as alternating subsounds
printf( &quot;play alternating...\n&quot; );
result = system-&gt;playSound( FMOD_CHANNEL_FREE, sound, false, &amp;channel );
ERRCHECK(result);

for(;;) {
    if ( kbhit() ) break;
    system-&gt;update();
    Sleep( 60 );
}
result = channel-&gt;stop();
ERRCHECK( result );
getch();

result = sound-&gt;release();
ERRCHECK(result);
result = system-&gt;close();
ERRCHECK(result);
result = system-&gt;release();
ERRCHECK(result);
return 0;

}
[/code:3s2gg8dt]

  • You must to post comments
0
0

More interesting tidbits. I modified the code to stitch together two static sounds that were created, not loaded-from-file (e.g., I create an empty sound, lock it, populate it, unlock it)
where previously I was using a PCMREADCALLBACK to populate a stream.

The code below works fine under FMOD 4.13.03, but crashes on FMOD 4.26.02 upon trying to play the soundsentence:
[quote:2nbpaoba]Unhandled exception at 0x1003f6cc in realtimestitching.exe: 0xC0000005: Access violation reading location 0xaf46719c.[/quote:2nbpaoba]

Am I mercilessly abusing something here? It [i:2nbpaoba]seems[/i:2nbpaoba] pretty straight-forward.

[code:2nbpaoba]#include <windows.h>

include <stdio.h>

include <conio.h>

include <math.h>

include "../../api/inc/fmod.hpp"

include "../../api/inc/fmod_errors.h"

typedef unsigned int uint;

void ERRCHECK(FMOD_RESULT result) {
if (result == FMOD_OK) return;
printf( "error (%d) %s\n", result, FMOD_ErrorString(result));
getch();
exit(-1);
}

int main( int argc, char *argv[] ) {

FMOD::System     *system;
FMOD::Sound      *sound;
FMOD::Sound      *subsound[2];
FMOD_CREATESOUNDEXINFO exinfo;
FMOD::Channel    *channel = 0;
FMOD_RESULT       result;

result = FMOD::System_Create(&amp;system);
ERRCHECK(result);

result = system-&gt;init( 1, FMOD_INIT_NORMAL, 0 );
ERRCHECK(result);

// Create parent stream
memset( &amp;exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO) );
exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
exinfo.defaultfrequency = 44100;
exinfo.numsubsounds     = 2;
exinfo.numchannels      = 1;
exinfo.format           = FMOD_SOUND_FORMAT_PCM16;
result = system-&gt;createSound( 0, FMOD_SOFTWARE | FMOD_LOOP_NORMAL | FMOD_OPENUSER,
                              &amp;exinfo, &amp;sound );
ERRCHECK(result);

// Build some tone data
short* A = new short[44100];
short* B = new short[44100];
float t = 0.0F;
for (uint i=0; i &lt; 44100; i++) {
    A[i] = (short)( sin(t) * 32767.0F );
    B[i] = (short)( sin(2.0*t) * 32767.0F );
    t += 0.05;
}

// CREATESOUNDEXINFO common to tone A &amp; B
FMOD_CREATESOUNDEXINFO  createsoundexinfo;
memset( &amp;createsoundexinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO) );
createsoundexinfo.cbsize            = sizeof(FMOD_CREATESOUNDEXINFO);           
createsoundexinfo.decodebuffersize  = 44100;                                      
createsoundexinfo.length            = 44100 * sizeof(short);
createsoundexinfo.numchannels       = 1;
createsoundexinfo.defaultfrequency  = 44100;
createsoundexinfo.format            = FMOD_SOUND_FORMAT_PCM16;

// Create tone A's static sound
int mode = FMOD_SOFTWARE | FMOD_OPENUSER | FMOD_LOOP_NORMAL;
result = system-&gt;createSound( 0, mode, &amp;createsoundexinfo, &amp;subsound[0] );
ERRCHECK(result);

void* p1; void* p2; uint l1, l2;
result = subsound[0]-&gt;lock( 0, 44100, &amp;p1, &amp;p2, &amp;l1, &amp;l2 );
ERRCHECK(result);
memcpy( p1, A, 2*44100 );       // populate A
subsound[0]-&gt;unlock(p1,p2,l1,l2);

// Create tone B's static sound
result = system-&gt;createSound( 0, mode, &amp;createsoundexinfo, &amp;subsound[1] );
ERRCHECK(result);
result = subsound[1]-&gt;lock( 0, 44100, &amp;p1, &amp;p2, &amp;l1, &amp;l2 );
ERRCHECK(result);
memcpy( p1, B, 2*44100 );       // populate B
subsound[1]-&gt;unlock(p1,p2,l1,l2);

// Set up subsounds
result = sound-&gt;setSubSound( 0, subsound[0] );
ERRCHECK(result);

result = sound-&gt;setSubSound( 1, subsound[1] );
ERRCHECK(result);

int soundlist[2] = { 0, 1 };
result = sound-&gt;setSubSoundSentence( soundlist, 2 );
ERRCHECK(result);

// Test the tones
printf( &quot;play tone 1...\n&quot; );
system-&gt;playSound( FMOD_CHANNEL_FREE, subsound[0], false, &amp;channel );
Sleep( 500 );
channel-&gt;stop();

printf( &quot;play tone 2...\n&quot; );
system-&gt;playSound( FMOD_CHANNEL_FREE, subsound[1], false, &amp;channel );
Sleep( 500 );
channel-&gt;stop();

// Play them as alternating subsounds
printf( &quot;play alternating...\n&quot; );
result = system-&gt;playSound( FMOD_CHANNEL_FREE, sound, false, &amp;channel );
ERRCHECK(result);

for(;;) {
    if ( kbhit() ) break;
    system-&gt;update();
    Sleep( 60 );
}
result = channel-&gt;stop();
ERRCHECK( result );
getch();

result = sound-&gt;release();
ERRCHECK(result);
result = system-&gt;close();
ERRCHECK(result);
result = system-&gt;release();
ERRCHECK(result);

delete[] A;
delete[] B;
return 0;

}
[/code:2nbpaoba]
Thanks in advance for any pointers,
Bill

  • You must to post comments
Showing 1 result
Your Answer

Please first to submit.