Jump to content
  • Advertisement
Sign in to follow this  
aregee

Threading problem writing to an AudioQueue buffer from a different class?

This topic is 2047 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Working with AudioQueue is a nice blend of c++ and Objective C with the issues that follows from mixing C++ classes with Objective C classes.

 

For example: you can not readily access the Objective C 'self' inside a C++ class.  You have to do one of two things as far as I have managed to think of:

 

1. declare and init a 'Self' = self in the global C++ scope.

2. Pass 'self' as user data to the AudioQueue structure and cast it to the appropriate type.

 

Sorry about the digression.  My problem is of a different kind.  I have the following AudioQueue callback:

void aqOutputBufferCallback(void *userData, AudioQueueRef aqRef, AudioQueueBufferRef aqBuffer) {
    char unsigned *buffer = aqBuffer->mAudioData;

    STAAudioStreamer *self = (__bridge STAAudioStreamer *)userData;

    if (self->isPaused) {
        int unsigned bufferSizeInSamples = self->bufferSizeInSamples * 2;
        for (int i = 0; i < bufferSizeInSamples; i++) {
            buffer[(i << 1) + 0] = (char unsigned)0x80;
            buffer[(i << 1) + 1] = (char unsigned)0x00;
        }
    }
    else {
        [self->audioFile getBytes:aqBuffer sampleCount:self->bufferSizeInSamples];

//        int unsigned bufferSizeInSamples = self->bufferSizeInSamples * 4;
//        for (int i = 0; i < bufferSizeInSamples; i++) {
//            buffer[i] = (char unsigned)(rand() % 0x100);
//        }
    }
    
    aqBuffer->mAudioDataByteSize = self->bufferSizeInSamples * 4;

    AudioQueueEnqueueBuffer(aqRef, aqBuffer, 0, NULL);
}

And I have the following method in a different class:

- (void)getBytes:(void *)buffer sampleCount:(long unsigned)count {
    char unsigned *uCharBuffer = (char unsigned *)buffer;

    long unsigned index = 0;
    for (long unsigned i = 0; i < count; i++) {
        index = i << 2;  //index = i * 4;
        uCharBuffer[index + 0] = 0x80;
        uCharBuffer[index + 1] = (char unsigned)(rand() % 0x100);
        uCharBuffer[index + 2] = 0x80;
        uCharBuffer[index + 3] = (char unsigned)(rand() % 0x100);
    }
}

It should fill the AudioQueue buffer with 'white noise', but it fails miserably with the following exception: 

 

'Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)'

 

Guessing 'GPFLT' means 'General Protection FauLT'

 

There is no stack trace, but if I remove the loop in the 'getBytes:sampleCount:' method, there is no crash.

 

I have considered that I might be writing outside of the buffer or even at a random address, but to me the code seems completely legit.  A similar code that I have commented out inside the callback is working just fine too, so it leaves me to wonder if I am having a thread issue access violation.

 

Does anyone have a hint what I can do to solve this problem, I am right about my hunch?  I am a real noob when it comes to programming with threads, and I don't want to build my wave file reader class into the audio stream class...

 

EDIT:

Oh, after running this thing several times, I suddenly got a crash with a log message:

'Loud(36531,0x7fff75b3f310) malloc: *** error for object 0x6000000dd960: Heap corruption detected, free list canary is damaged

*** set a breakpoint in malloc_error_break to debug'

 

Maybe I am writing random memory after all?

Edited by aregee

Share this post


Link to post
Share on other sites
Advertisement

Ah...  Time to go to bed for me, lol...  It was indeed a garbage pointer I sent into the class...  I sent the AudioQueueBufferRef 'aqBuffer' instead of what I should have sent, 'buffer'.  It is now working.  Sorry for the premature post.  I will rename the variable to 'aqBufferRef' now so I don't make the same mistake again...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!