Jump to content

  • Log In with Google      Sign In   
  • Create Account

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


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
1 reply to this topic

#1 aregee   Members   -  Reputation: 1025

Like
0Likes
Like

Posted 07 March 2014 - 06:27 PM

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, 07 March 2014 - 06:35 PM.


Sponsor:

#2 aregee   Members   -  Reputation: 1025

Like
0Likes
Like

Posted 07 March 2014 - 06:46 PM

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






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS