How to use CoreAudio?

KeyReal

Registered
MacOS CoreAudio buffer playback produces annoying noise between correct sound.

I'm interested to play valid .wav data though the buffer.

Why I'm playing a .wav? It has valid data.

What I'm trying to achieve is to understand how to write correctly to the sound buffer.
I'm porting a music engine to MacOS ....

I have this C code:

C:
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <stdio.h>
#include <AudioToolbox/AudioToolbox.h>

FILE *fp;

typedef struct TwavHeader{
            
    char RIFF[4];
    uint32_t RIFFChunkSize;
    char WAVE[4];
            
    char fmt[4];
    uint32_t Subchunk1Size;
    uint16_t AudioFormat;
    uint16_t NumOfChan;
    uint32_t SamplesPerSec;
    uint32_t bytesPerSec;
    uint16_t blockAlign;
    uint16_t bitsPerSample;
            
    char Subchunk2ID[4];
    uint32_t Subchunk2Size;
}TwavHeader;



typedef struct SoundState {
    bool done;
}SoundState;


void auCallback(void *inUserData, AudioQueueRef queue, AudioQueueBufferRef buffer) {
 
    
    buffer->mAudioDataByteSize = 1024*4;
    
    int numToRead = buffer->mAudioDataByteSize / sizeof(float) * 2;

    void *p = malloc(numToRead);

    fread(p, numToRead,1,fp);
    

    void *myBuf = buffer->mAudioData;


    for (int i=0; i < numToRead / 2; i++) {
       uint16_t w = *(uint16_t *)&(p[i*sizeof(uint16_t)]);
      
            float f = ((float)w / (float)0x8000) - 1.0;
        *(float *)&(myBuf[i*sizeof(float)]) = f;
    }
    

    free(p);
    AudioQueueEnqueueBuffer(queue, buffer, 0, 0);
}

void checkError(OSStatus error){
    if (error != noErr) {
        printf("Error: %d", error);
        exit(error);
    }
}

int main(int argc, const char * argv[]) {
    
    printf("START\n");
    
    TwavHeader theHeader;

    
    fp = fopen("/Users/kirillkranz/Documents/mytralala-code/CoreAudioTest/unreal.wav", "r");
    fread(&theHeader, sizeof(TwavHeader),1,fp);
    
    printf("%i\n",theHeader.bitsPerSample);
    
    
    
    
    

    AudioStreamBasicDescription auDesc =  {};
    
    auDesc.mSampleRate = theHeader.SamplesPerSec;
    auDesc.mFormatID = kAudioFormatLinearPCM;
    auDesc.mFormatFlags = kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsPacked;
    auDesc.mBytesPerPacket = 8;
    auDesc.mFramesPerPacket = 1;
    auDesc.mBytesPerFrame = 8;
    auDesc.mChannelsPerFrame = 2;
    auDesc.mBitsPerChannel = 32;
    
    
    
    AudioQueueRef auQueue = 0;
    AudioQueueBufferRef auBuffers[2] ={};
    
    // our persistent state for sound playback
    SoundState soundState=  {};
    soundState.done=false;
    
    
    OSStatus err;

    // most of the 0 and nullptr params here are for compressed sound formats etc.
    err = AudioQueueNewOutput(&auDesc, &auCallback, &soundState, 0, 0, 0, &auQueue);
    checkError(err);
    
    // generate buffers holding at most 1/16th of a second of data
    uint32_t bufferSize = auDesc.mBytesPerFrame * (auDesc.mSampleRate / 16);
    err = AudioQueueAllocateBuffer(auQueue, bufferSize, &(auBuffers[0]));
    checkError(err);

        
    err = AudioQueueAllocateBuffer(auQueue, bufferSize, &(auBuffers[1]));
    checkError(err);
            
    // prime the buffers
    auCallback(&soundState, auQueue, auBuffers[0]);
    auCallback(&soundState, auQueue, auBuffers[1]);

    // enqueue for playing
    AudioQueueEnqueueBuffer(auQueue, auBuffers[0], 0, 0);
    AudioQueueEnqueueBuffer(auQueue, auBuffers[1], 0, 0);

    // go!
    AudioQueueStart(auQueue, 0);
            
    
    
    
    char rxChar[10]; scanf( "%s", &rxChar);
    printf("FINISH");
    
    fclose(fp);
    // be nice even it doesn't really matter at this point
    if (auQueue)
        AudioQueueDispose(auQueue, true);
}
 
Back
Top