0
0

hi all,

okay i finally tracked down the source of all my problems. DONT SET THE SOFTWARE FORMAT!! let fmod do it by default, unless you really really know what yer doing. i thought that this was fine, tried both 1 channel and 2 channels, but no matter what i put in here, it messed up the file writing, the dsp, and the audio in general:

[code:3ghuj649]

// I RECOMMEND NOT DOING THIS AT ALL, EVER!!! COMMENT IT OUT!!

//result = system->setSoftwareFormat(OUTPUTRATE, FMOD_SOUND_FORMAT_PCM16, 2, 0, FMOD_DSP_RESAMPLER_LINEAR);
//ERRCHECK(result);

[/code:3ghuj649]

once i got rid of that, EVRYTHING started running much smoother. swear to god (and i dont mean brett).

first off, if you want to write to disk via a DSP callback, 16bit, stereo, start with the basic callback example, and the basic record to file example and use this in the callback: note that i have an encapsulated file write so my write to disk is just a little different than yours might be, using stock example:

[code:3ghuj649]
int dpp = 0;

unsigned int count, count2;

for (count = 0; count < length; count++) 
{ 

    for (count2 = 0; count2 < outchannels; count2++)
    {             

        outbuffer[(count * outchannels) + count2] = inbuffer[(count * inchannels) + count2];

        float valu = inbuffer[(count * inchannels) + count2] * 32767.0; 

        //make sure it doesnt round off to a over-max value
        if (valu > 32767)
           valu = 32767;
        if (valu < -32767)
           valu = -32767;

        short writ = (short)valu;

        //using a file write class
        fp.write(sizeof(writ), (const char *)&writ, &dpp);    

        datalength += dpp;

    }
} 

[/code:3ghuj649]

use the file open and write wav header as per the example code, make sure datalength, and your file pointer is a class member or of global/module scope. you dont need any of the other stuff from the recordtodisk example if you are doing through dsp. just the datalength variable, the write header code. here is my final shut-down when i’m done recording:

[code:3ghuj649]
/*
Write back the wav header now that we know its length.
*/
WriteWavHeader(&fp, datalength);

fp.flush();
fp.close();

[/code:3ghuj649]

again my ‘fp’ is a bit different than stock, and i hardcoded :

[code:3ghuj649]

 channels = 2;
 bits = 16;
 rate = 48000;

[/code:3ghuj649]

so i don’t have to pass a sound object.

my next problem was actually getting it in stereo. i recommend forcing speaklerMode to stereo, just to be sure your 5.1 system isn’t mucking things up. i combined the pitch detection example with the record to disk example, plus the dsp example, so you must must must set everything to two channels, not one as in the examples:

[code:3ghuj649]

/*
    Create a sound to record to.
*/
memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));

exinfo.cbsize           = sizeof(FMOD_CREATESOUNDEXINFO);
exinfo.numchannels      = 2;                 //NOTE TWO CHANNELS NOT ONE
exinfo.format           = FMOD_SOUND_FORMAT_PCM16;
exinfo.defaultfrequency = OUTPUTRATE;
exinfo.length           = exinfo.defaultfrequency * sizeof(short) * exinfo.numchannels * 5;

result = system->createSound(0, FMOD_2D | FMOD_SOFTWARE | FMOD_LOOP_NORMAL | FMOD_OPENUSER, &exinfo, &sound);
ERRCHECK(result);

result = system->recordStart(sound, true);
ERRCHECK(result);

Sleep(60);   //no less than a 60ms sleep before playback

result = system->playSound(FMOD_CHANNEL_REUSE, sound, false, &channel);
ERRCHECK(result);

//screw the feedback, make sure you have some volume to know it's working
result = channel->setVolume(0.5);

[/code:3ghuj649]

also DO NOT use the default 0 channels for the dsp description, use 2:

[code:3ghuj649]

FMOD_DSP_DESCRIPTION dspdesc;

memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION));

strcpy(dspdesc.name, "record DSP unit");
dspdesc.channels = 2; // USE 2 USE 2 !!!
dspdesc.read = recordDSPCallback;
dspdesc.userdata = (void *)0x12345678;

result = system->createDSP(&dspdesc, &record);
ERRCHECK(result);

result = system->addDSP(record);
ERRCHECK(result);

[/code:3ghuj649]

and that is pretty much it.

i was having horrible problems with popping sounds and crummy audio in general, when i had lots of sounds playing, so make absolutely sure you call system->update() FREQUENTLY, i do it every 20 ms. but also, don’t update the listener position too much, it seems to cause noise too. i do it every 60 ms.

AND very important, for my needs anyway, i set a maximum of 256 "virtual" voices that i cycle, and i was setting real channels to 32, thinking this was wise. for me, it was NOT.

[code:3ghuj649]
result = system->setSoftwareChannels(256); //real channels
ERRCHECK(result);

result = system->init(256, FMOD_INIT_NORMAL, 0); //virtual channels
ERRCHECK(result);
[/code:3ghuj649]

i set real and virtual to be both 256, and lo-and-behold, all my popping noises and mixer artifacts vanished.

i hope you find this useful! it represents the pulling of many hairs from my rapidly thinning scalp.

cheers,
j

  • You must to post comments
0
0

oh forgot to mention, don’t use FMOD_HARDWARE for sounds, and expect them to appear in the dsp callback.

also, before i discovered the magic commenting out of setSoftwareFormat, i was getting really bizzare FMOD errors in getSpectrum. again, nukeing setSoftwareFormat, upping my real channels to 256, expressly setting formats to 2 channels, and frequent FMOD system->update() calls fixed EVERYTHING!!

  • You must to post comments
0
0

The limits of short int are +32767 and -32768 so when you round value you have to check
[code:1dxra44i]if (valu < -32768) // you wrote ( if (valu < -32767) )
valu = -32768 // you wrote valu = -32767[/code:1dxra44i]

Regards,
Franco

  • You must to post comments
Showing 2 results
Your Answer

Please first to submit.