0
0

Hello, I am working on an iPhone app where I am recording audio. There is a record and stop recording button. The first time the app loads, and I record something then play it back, it is perfect. If I then goto record another recording, it is all messed up. It sometimes contains part of my previous recording, or just messes up the audio. Here are my record and stop recording methods:

[code:3hro9n5d]
//==========================================================================
– (void)recordWav:(NSString *)file
{
FMOD_RESULT result = FMOD_OK;
char buffer[200] = {0};

[self stopRecording];
self.recording = true;

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

[[NSString stringWithFormat:@"%@/%@", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0], file] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];    
outFile = fopen(buffer, "wb");
if (!outFile)
{
    fprintf(stderr, "Error! Could not open record.wavw output file.\n");
    return;
}

/*
 Write out the wav header.  As we don't know the length yet it will be 0
 */

writeWavHeader(outFile, sound, dataLength);}

//==========================================================================
– (void)stopRecording
{
self.recording = false;
if (outFile != NULL)
{
/*
Write back the wav header now that we know its length
*/
writeWavHeader(outFile, sound, dataLength);

    fclose(outFile);
    outFile = NULL;
    dataLength = 0;
}

}
[/code:3hro9n5d]

I am guessing the old buffer is not getting reset or something; I took this code from the recording demo from the examples.

Any help greatly appreciated!

  • You must to post comments
0
0

I think I may have discovered the problem.

I followed the recording example found in the FMOD folder. In that example, the timer started in the viewWillAppear method, then invalidated in viewDidDisappear.

In my app, I have a FMOD singleton class. Right now, as you can see above I am calling the line:

[code:2laqgitl]
timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(timerUpdate:) userInfo:nil repeats:YES];
[/code:2laqgitl]

in my setUp method, and I am never invalidating the timer.

I tried moving that line to my record method, and invalidating in my stop record, but I am still having the issue.

Do you see this being the problem? Thanks a lot!

  • You must to post comments
0
0

The FMOD::Sound that you record to is at its core just a buffer. It will not be wiped clean when you do another recording, so if the second record is shorter than the first you will still have the ‘left over’ recording in the part of the buffer that wasn’t written to.

If you want to wipe all or part of the buffer, use the Sound::lock and Sound::unlock feature to access the buffer, then memset the data to 0.

  • You must to post comments
0
0

You need to make sure that code doesn’t run once you have stopped the recording. Otherwise the record position will reset back to 0, and your code will write out from your last record position to 0.

  • You must to post comments
0
0

[quote="mathew":zpoqu8fq]The FMOD::Sound that you record to is at its core just a buffer. It will not be wiped clean when you do another recording, so if the second record is shorter than the first you will still have the ‘left over’ recording in the part of the buffer that wasn’t written to.

If you want to wipe all or part of the buffer, use the Sound::lock and Sound::unlock feature to access the buffer, then memset the data to 0.[/quote:zpoqu8fq]

Thanks! Would this be done in the stop record method?

  • You must to post comments
0
0

[quote="mathew":wq8enosf]You need to make sure that code doesn’t run once you have stopped the recording. Otherwise the record position will reset back to 0, and your code will write out from your last record position to 0.[/quote:wq8enosf]

I ended up fixing the timer issue, it was running basically the whole lifetime of the app since I was never invalidating it. What I did was start the timer in my start record, and invalidate it in stop record.

BUT….

The issue with "blank sound" after the first recording still exists and I have no idea why.

Below is my entire FMODController.mm if you wouldn’t mind taking a look at it.

Once again thanks for your help!

[code:wq8enosf]

//
// FMODController.m
// blurts
//
// Created by Bob Grube on 6/8/11.
// Copyright 2011 Seisan. All rights reserved.
//

import "FMODController.h"

import "JSON.h"

import "FileManager.h"

@implementation FMODController
@synthesize recording;

define PACKED __attribute((packed)) // gcc packed

static FMODController *sharedInstance = nil;
int qwipTime = 0;

//==========================================================================
void ERRCHECK(FMOD_RESULT result)
{
if (result != FMOD_OK)
{
fprintf(stderr, "FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
exit(-1);
}
}

//==========================================================================
-(void)setUp {
system = NULL;
sound = NULL;
bytesPerSample = 0;
bytesPerSecond = 0;
dataLength = 0;
outFile = NULL;

//-------

const unsigned int      RECORD_LENGTH_SECS  = 3;
FMOD_RESULT             result              = FMOD_OK;
unsigned int            version             = 0;
FMOD_CREATESOUNDEXINFO  exinfo              = {0};

/*
 Create a System object and initialize
 */    
result = FMOD::System_Create(&system); 
ERRCHECK(result);

result = system->getVersion(&version);
ERRCHECK(result);

if (version < FMOD_VERSION)
{
    fprintf(stderr, "You are using an old version of FMOD %08x.  This program requires %08x\n", version, FMOD_VERSION);
    exit(-1);
}
//FMOD_IPHONE_EXTRADRIVERDATA edd;
//edd.forceSpeakerOutput = true;
//edd.forceMixWithOthers = YES;

result = system->init(2, FMOD_INIT_NORMAL | FMOD_INIT_ENABLE_PROFILE, NULL);
ERRCHECK(result);  

memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));

exinfo.cbsize           = sizeof(FMOD_CREATESOUNDEXINFO);
exinfo.numchannels      = 2;
exinfo.format           = FMOD_SOUND_FORMAT_PCM16;
exinfo.defaultfrequency = 8000;
exinfo.length           = exinfo.defaultfrequency * sizeof(short) * exinfo.numchannels * RECORD_LENGTH_SECS;

bytesPerSample = sizeof(short) * exinfo.numchannels;
bytesPerSecond = exinfo.defaultfrequency * bytesPerSample;

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

result = system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dspecho);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsppitchshift);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_LOWPASS, &dsplowpass);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_HIGHPASS, &dsphighpass);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_FLANGE, &dspflange);
ERRCHECK(result);    
result = system->createDSPByType(FMOD_DSP_TYPE_DISTORTION, &dspdistortion);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_CHORUS, &dspchorus);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_PARAMEQ, &dspparameq);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_ITECHO, &dspitecho);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_DELAY, &dspdelay);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_TREMOLO, &dsptremolo);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_REVERB, &dspreverb);
ERRCHECK(result);

self.recording = false;

}

//==========================================================================
– (void)timerUpdate:(NSTimer *)timer
{

NSLog(@"timer");
/*
 Main loop
 */
static unsigned int lastRecordPos   = 0;
FMOD_RESULT         result          = FMOD_OK;
unsigned int        recordPos       = 0;
unsigned int        soundLength     = 0;

if (outFile != NULL)
{

    result = sound->getLength(&soundLength, FMOD_TIMEUNIT_PCM);
    ERRCHECK(result);

    //NSLog(@"one");

    result = system->getRecordPosition(0, &recordPos);
    ERRCHECK(result);

    //NSLog(@"two");


    if (recordPos != lastRecordPos)
    {
        void           *ptr1        = NULL;
        void           *ptr2        = NULL;
        int             blockLength = 0;
        unsigned int    len1        = 0;
        unsigned int    len2        = 0;

        blockLength = (int)recordPos - (int)lastRecordPos;
        if (blockLength < 0)
        {
            blockLength += soundLength;
        }

        /*
         Lock the sound to get access to the raw data
         */

        result = sound->lock(lastRecordPos * bytesPerSample, blockLength * bytesPerSample, &ptr1, &ptr2, &len1, &len2);
        ERRCHECK(result);

        //NSLog(@"three");


        /*
         Write it to disk
         */
        if (ptr1 && len1)
        {
            dataLength += fwrite(ptr1, 1, len1, outFile);
        }
        if (ptr2 && len2)
        {
            dataLength += fwrite(ptr2, 1, len2, outFile);
        }

        /*
         Unlock the sound to allow FMOD to use it again
         */
        result = sound->unlock(ptr1, ptr2, len1, len2);
        ERRCHECK(result);

        //NSLog(@"four");

    }

    lastRecordPos = recordPos;
}

result = system->update();
ERRCHECK(result);

//NSLog(@"five");

}

//==========================================================================
void writeWavHeader(FILE *file, FMOD::Sound *sound, int length)
{
int channels;
int bits;
float rate;
FMOD_SOUND_FORMAT format;

if (!sound)
{
    return;
}

fseek(file, 0, SEEK_SET);

sound->getFormat(NULL, &format, &channels, &bits);
sound->getDefaults(&rate, NULL, NULL, NULL);

{
    /*
     WAV Structures
     */
    typedef struct
    {
        signed char id[4];
        int         size;
    } RiffChunk;

    struct
    {
        RiffChunk       chunk           __PACKED;
        unsigned short  wFormatTag      __PACKED;    /* format type  */
        unsigned short  nChannels       __PACKED;    /* number of channels (i.e. mono, stereo...)  */
        unsigned int    nSamplesPerSec  __PACKED;    /* sample rate  */
        unsigned int    nAvgBytesPerSec __PACKED;    /* for buffer estimation  */
        unsigned short  nBlockAlign     __PACKED;    /* block size of data  */
        unsigned short  wBitsPerSample  __PACKED;    /* number of bits per sample of mono data */
    } __PACKED FmtChunk  = { {{'f','m','t',' '}, sizeof(FmtChunk) - sizeof(RiffChunk) }, 1, channels, (int)rate, (int)rate * channels * bits / 8, 1 * channels * bits / 8, bits };

    if (format == FMOD_SOUND_FORMAT_PCMFLOAT)
    {
        FmtChunk.wFormatTag = 3;
    }

    struct
    {
        RiffChunk   chunk;
    } DataChunk = { {{'d','a','t','a'}, length } };

    struct
    {
        RiffChunk   chunk;
        signed char rifftype[4];
    } WavHeader = { {{'R','I','F','F'}, sizeof(FmtChunk) + sizeof(RiffChunk) + length }, {'W','A','V','E'} };

    /*
     Write out the WAV header
     */
    fwrite(&WavHeader, sizeof(WavHeader), 1, file);
    fwrite(&FmtChunk, sizeof(FmtChunk), 1, file);
    fwrite(&DataChunk, sizeof(DataChunk), 1, file);
}

}

//==========================================================================
– (void)recordWav:(NSString *)file
{
FMOD_RESULT result = FMOD_OK;
char buffer[200] = {0};

//lock
void           *ptr1        = NULL;
void           *ptr2        = NULL;
unsigned int    len1        = 0;
unsigned int    len2        = 0;


/*
 Lock the sound to get access to the raw data
 */
unsigned int length = 0;

result = sound->getLength(&length, FMOD_TIMEUNIT_PCMBYTES);
ERRCHECK(result);

result = sound->lock(0, length, &ptr1, &ptr2, &len1, &len2);
ERRCHECK(result);


memset(ptr1, 0, len1);
memset(ptr2, 0, len2);

//unlock
result = sound->unlock(ptr1, ptr2, len1, len2);
ERRCHECK(result);


//[self stopRecording];
self.recording = true;


result = system->recordStart(0, sound, true);
ERRCHECK(result);
timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(timerUpdate:) userInfo:nil repeats:YES];    


[[NSString stringWithFormat:@"%@/%@", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0], file] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];    
outFile = fopen(buffer, "wb");
if (!outFile)
{
    fprintf(stderr, "Error! Could not open record.wavw output file.\n");
    return;
}

/*
 Write out the wav header.  As we don't know the length yet it will be 0
 */

writeWavHeader(outFile, sound, dataLength);

}

//==========================================================================
– (void)stopRecording
{
FMOD_RESULT result = FMOD_OK;

[timer invalidate];
//timer = nil;

result = system->recordStop(0);

self.recording = false;
if (outFile != NULL)
{
    /*
     Write back the wav header now that we know its length
     */
    writeWavHeader(outFile, sound, dataLength);

    fclose(outFile);
    outFile = NULL;
    dataLength = 0;

}

}

//==========================================================================
– (void)playWav:(NSString *)file
{
FMOD_RESULT result = FMOD_OK;
char buffer[200] = {0};

[[NSString stringWithFormat:@"%@/%@", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0], file] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding]; 


result = system->createSound(buffer, FMOD_SOFTWARE, NULL, &sound);
ERRCHECK(result);


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

}

//==========================================================================
– (void)playLocal:(NSString *)file
{
FMOD_RESULT result = FMOD_OK;
char buffer[200] = {0};

[[NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] resourcePath], file] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];




result = system->createSound(buffer, FMOD_SOFTWARE, NULL, &sound2);
ERRCHECK(result);


result = system->playSound(FMOD_CHANNEL_FREE, sound2, false, &channel2);
ERRCHECK(result);


result = channel2->setVolume(0.2);
ERRCHECK(result);

timer2 = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(stopBackground) userInfo:nil repeats:YES];    

}

//==========================================================================
– (void)stopBackground
{
unsigned int length;

sound->getLength(&length, FMOD_TIMEUNIT_MS);

qwipTime += 1;


if(qwipTime >= length)
{
    [timer2 invalidate];

    channel2->stop();
    qwipTime = 0;
    length = 0;
}

}

//==========================================================================
– (void)stopWave
{

channel->stop();
channel2->stop();

}

//==========================================================================
– (void) setAudioPositionInSeconds: (int) seconds
{
FMOD_RESULT result = FMOD_OK;
result = channel->setPosition(seconds * 1000, FMOD_TIMEUNIT_MS);
}

//==========================================================================
+ (FMODController*)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[super allocWithZone:NULL] init];
}

return sharedInstance;

}

//==========================================================================
// We don’t want to allocate a new instance, so return the current one.
+ (id)allocWithZone:(NSZone*)zone
{
return [[self sharedInstance] retain];
}

//==========================================================================
// Equally, we don’t want to generate multiple copies of the singleton.
– (id)copyWithZone:(NSZone *)zone
{
return self;
}

//==========================================================================
// Once again – do nothing, as we don’t have a retain counter for this object.
– (id)retain
{
return self;
}

//==========================================================================
// Replace the retain counter so we can never release this object.
– (NSUInteger)retainCount
{
return NSUIntegerMax;
}

//==========================================================================
// This function is empty, as we don’t want to let the user release this object.
– (void)release
{

}

//==========================================================================
//Do nothing, other than return the shared instance – as this is expected from autorelease.
– (id)autorelease
{
return self;
}

@end
[/code:wq8enosf]

  • You must to post comments
0
0

If you are finished with the contents of the sound buffer, then yes you could wipe it in the stop function, after you have stopped the recording.

  • You must to post comments
0
0

As I said in one of the above posts:
[quote:1k00le7w]Are you resetting lastRecordPos when you start your next recording? If not that may explain why you get silence written out the length of the last recording.[/quote:1k00le7w]

When you do your second recording, lastRecordPos will still have its old value, you need to reset it in either stop or start.

  • You must to post comments
0
0

I decided the easiest place to clear the buffer would be at the beginning of the record method, but I am having issues. I have yet to really use the lock or unlock functions, but I looked at examples and copied some code and I still can’t get it working. I get an error #37, "An invalid parameter was passed to the function."

Here is my modified record method:

[code:28br8kd2]
//==========================================================================
– (void)recordWav:(NSString *)file
{
FMOD_RESULT result = FMOD_OK;
char buffer[200] = {0};

//lock
void           *ptr1        = NULL;
void           *ptr2        = NULL;
unsigned int    len1        = 0;
unsigned int    len2        = 0;


/*
 Lock the sound to get access to the raw data
 */
result = sound->lock(0, 0, &ptr1, &ptr2, &len1, &len2);
ERRCHECK(result);

memset(buffer, 0, 200);

//unlock
result = sound->unlock(&ptr1, &ptr2, len1, len2);
ERRCHECK(result);


[self stopRecording];
self.recording = true;

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

[[NSString stringWithFormat:@"%@/%@", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0], file] getCString:buffer maxLength:200 encoding:NSASCIIStringEncoding];    
outFile = fopen(buffer, "wb");
if (!outFile)
{
    fprintf(stderr, "Error! Could not open record.wavw output file.\n");
    return;
}

/*
 Write out the wav header.  As we don't know the length yet it will be 0
 */

writeWavHeader(outFile, sound, dataLength);

}
[/code:28br8kd2]

I am doing the clearing near the top using memset as you suggested, but I know I am probably doing something horribly wrong. I get the error #37 when trying to unlock the sound after the memset.

Thanks for any help, I really do greatly appreciate it!

  • You must to post comments
0
0

[quote="mathew":1ngjqn06]As I said in one of the above posts:
[quote:1ngjqn06]Are you resetting lastRecordPos when you start your next recording? If not that may explain why you get silence written out the length of the last recording.[/quote:1ngjqn06]

When you do your second recording, lastRecordPos will still have its old value, you need to reset it in either stop or start.[/quote:1ngjqn06]

Finally! I believed I fixed it. I had attempted doing this when you first suggested it, but I at that point I was still having that timer issue. I think the combination of fixing both issues resolved the problem.

Thanks again for your continued help!

For licensing info I should direct my client to this e-mail correct: sales@fmod.org?

  • You must to post comments
0
0

Firstly, sound->lock
– The second parameter is length in bytes, you need a meaningful value here, most likely the length of the sound (Sound::getLength).
memset
– You should be clearing the locked memory, not your buffer so:
[code:2jfo4j0r]
memset(ptr1, 0, len1);
memset(ptr2, 0, len2);
[/code:2jfo4j0r]
sound->unlock
– The first two parameters should be ptr1 and ptr2 to not &ptr1 and &ptr2.

  • You must to post comments
0
0

Excellent, I’m glad it’s working for you now.

Yes, please direct any licensing questions to sales@fmod.org.

  • You must to post comments
0
0

[quote="mathew":3aj2izhn]Firstly, sound->lock
– The second parameter is length in bytes, you need a meaningful value here, most likely the length of the sound (Sound::getLength).
memset
– You should be clearing the locked memory, not your buffer so:
[code:3aj2izhn]
memset(ptr1, 0, len1);
memset(ptr2, 0, len2);
[/code:3aj2izhn]
sound->unlock
– The first two parameters should be ptr1 and ptr2 to not &ptr1 and &ptr2.[/quote:3aj2izhn]

I got it working, I am not hearing parts of old recordings in my new one. But I am still experiencing a ‘blank sound’ for the duration of the original one before my new recording plays.

Do I need to reset the position to the beginning of the sound or something?

Thanks a lot! I am understanding FMOD more and more.

Heres what I ended up with:
[code:3aj2izhn]
unsigned int length = 0;

result = sound->getLength(&length, FMOD_TIMEUNIT_PCMBYTES);
ERRCHECK(result);


result = sound->lock(0, length, &ptr1, &ptr2, &len1, &len2);
ERRCHECK(result);

memset(ptr1, 0, len1);
memset(ptr2, 0, len2);

//unlock
result = sound->unlock(ptr1, ptr2, len1, len2);
ERRCHECK(result);

[/code:3aj2izhn]

  • You must to post comments
0
0

Sound::recordStop should reset back to the start of the buffer. If you look at the recording example you’ll notice that when you press ‘stop’ the reported position snaps back to 0, then when you start again the position ticks up from 0. Perhaps you could post some more of your code?

  • You must to post comments
0
0

[quote="mathew":q0ynqeg6]Sound::recordStop should reset back to the start of the buffer. If you look at the recording example you’ll notice that when you press ‘stop’ the reported position snaps back to 0, then when you start again the position ticks up from 0. Perhaps you could post some more of your code?[/quote:q0ynqeg6]

Here is my FMOD setUp method and timerUpdate.

[code:q0ynqeg6]
//==========================================================================
-(void)setUp {
system = NULL;
sound = NULL;
bytesPerSample = 0;
bytesPerSecond = 0;
dataLength = 0;
outFile = NULL;

//-------

const unsigned int      RECORD_LENGTH_SECS  = 3;
FMOD_RESULT             result              = FMOD_OK;
unsigned int            version             = 0;
FMOD_CREATESOUNDEXINFO  exinfo              = {0};

/*
 Create a System object and initialize
 */    
result = FMOD::System_Create(&system); 
ERRCHECK(result);

result = system->getVersion(&version);
ERRCHECK(result);

if (version < FMOD_VERSION)
{
    fprintf(stderr, "You are using an old version of FMOD %08x.  This program requires %08x\n", version, FMOD_VERSION);
    exit(-1);
}
//FMOD_IPHONE_EXTRADRIVERDATA edd;
//edd.forceSpeakerOutput = true;
//edd.forceMixWithOthers = YES;

result = system->init(2, FMOD_INIT_NORMAL | FMOD_INIT_ENABLE_PROFILE, NULL);
ERRCHECK(result);  

memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));

exinfo.cbsize           = sizeof(FMOD_CREATESOUNDEXINFO);
exinfo.numchannels      = 2;
exinfo.format           = FMOD_SOUND_FORMAT_PCM16;
exinfo.defaultfrequency = 8000;
exinfo.length           = exinfo.defaultfrequency * sizeof(short) * exinfo.numchannels * RECORD_LENGTH_SECS;

bytesPerSample = sizeof(short) * exinfo.numchannels;
bytesPerSecond = exinfo.defaultfrequency * bytesPerSample;

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

result = system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dspecho);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsppitchshift);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_LOWPASS, &dsplowpass);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_HIGHPASS, &dsphighpass);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_FLANGE, &dspflange);
ERRCHECK(result);    
result = system->createDSPByType(FMOD_DSP_TYPE_DISTORTION, &dspdistortion);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_CHORUS, &dspchorus);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_PARAMEQ, &dspparameq);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_ITECHO, &dspitecho);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_DELAY, &dspdelay);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_TREMOLO, &dsptremolo);
ERRCHECK(result);
result = system->createDSPByType(FMOD_DSP_TYPE_REVERB, &dspreverb);
ERRCHECK(result);

timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(timerUpdate:) userInfo:nil repeats:YES];    

self.recording = false;

}
[/code:q0ynqeg6]
[code:q0ynqeg6]
//==========================================================================
– (void)timerUpdate:(NSTimer )timer
{
/

Main loop
*/
static unsigned int lastRecordPos = 0;
FMOD_RESULT result = FMOD_OK;
unsigned int recordPos = 0;
unsigned int soundLength = 0;

if (outFile != NULL)
{
    result = sound->getLength(&soundLength, FMOD_TIMEUNIT_PCM);
    ERRCHECK(result);

    result = system->getRecordPosition(0, &recordPos);
    ERRCHECK(result);

    if (recordPos != lastRecordPos)
    {
        void           *ptr1        = NULL;
        void           *ptr2        = NULL;
        int             blockLength = 0;
        unsigned int    len1        = 0;
        unsigned int    len2        = 0;

        blockLength = (int)recordPos - (int)lastRecordPos;
        if (blockLength < 0)
        {
            blockLength += soundLength;
        }

        /*
         Lock the sound to get access to the raw data
         */

        result = sound->lock(lastRecordPos * bytesPerSample, blockLength * bytesPerSample, &ptr1, &ptr2, &len1, &len2);
        ERRCHECK(result);


        /*
         Write it to disk
         */
        if (ptr1 && len1)
        {
            dataLength += fwrite(ptr1, 1, len1, outFile);
        }
        if (ptr2 && len2)
        {
            dataLength += fwrite(ptr2, 1, len2, outFile);
        }

        /*
         Unlock the sound to allow FMOD to use it again
         */
        result = sound->unlock(ptr1, ptr2, len1, len2);
        ERRCHECK(result);
    }

    lastRecordPos = recordPos;
}

result = system->update();
ERRCHECK(result);

}
[/code:q0ynqeg6]

What does the variable RECORD_LENGTH_SECS = 3; determine? I tried changing that around and I get crashes. The max recording recording length allowed in the app is 30 seconds. I think thinking that this line might be the culprit, since there is usually about a 3 second delay before the actually recording begins to play (only on the 2nd recording not the first).

  • You must to post comments
0
0

RECORD_LENGTH_SECS is the length of the record buffer in seconds, the larger the value the more memory will be used. However if you are using looping record, you won’t need to set it very large.

Are you resetting lastRecordPos when you start your next recording? If not that may explain why you get silence written out the length of the last recording.

  • You must to post comments
0
0

[quote="mathew":137gs92u]RECORD_LENGTH_SECS is the length of the record buffer in seconds, the larger the value the more memory will be used. However if you are using looping record, you won’t need to set it very large.

Are you resetting lastRecordPos when you start your next recording? If not that may explain why you get silence written out the length of the last recording.[/quote:137gs92u]

lastRecordPos is local to timerUpdate. I tried to bring it out to the class and reset it when the recording starts, but then I experiencing very strange recordings.

  • You must to post comments
Showing 16 results
Your Answer

Please first to submit.