Changeset 1322:8da3bcb947c5 in mediastreamer2 for src/macsnd.c


Ignore:
Timestamp:
Mar 23, 2011 4:45:35 PM (2 years ago)
Author:
Simon Morlat <simon.morlat@…>
Branch:
default
Message:

new audio unit based filter for macosx.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/macsnd.c

    r1321 r1322  
    6060#define CHECK_AURESULT(call)    do{ int _err; if ((_err=(call))!=noErr) ms_error( #call ": error [%i] %s %s",_err,GetMacOSStatusErrorString(_err),GetMacOSStatusCommentString(_err)); }while(0) 
    6161 
     62static void show_format(const char *name, AudioStreamBasicDescription * deviceFormat) 
     63{ 
     64        ms_message("Format for %s", name); 
     65        ms_message("mSampleRate = %g", deviceFormat->mSampleRate); 
     66        unsigned int fcc= ntohl(deviceFormat->mFormatID); 
     67        char outName[5]; 
     68        memcpy(outName,&fcc,4); 
     69        outName[4] = 0; 
     70        ms_message("mFormatID = %s", outName); 
     71        ms_message("mFormatFlags = %08lX", deviceFormat->mFormatFlags); 
     72        ms_message("mBytesPerPacket = %ld", deviceFormat->mBytesPerPacket); 
     73        ms_message("mFramesPerPacket = %ld", deviceFormat->mFramesPerPacket); 
     74        ms_message("mChannelsPerFrame = %ld", deviceFormat->mChannelsPerFrame); 
     75        ms_message("mBytesPerFrame = %ld", deviceFormat->mBytesPerFrame); 
     76        ms_message("mBitsPerChannel = %ld", deviceFormat->mBitsPerChannel); 
     77} 
     78 
     79 
    6280typedef struct AUCommon{ 
    6381        int dev; 
     
    83101        AudioDeviceID dev; 
    84102        int removed; 
     103        int rate; /*the nominal rate of the device*/ 
    85104} AuCard; 
    86105 
     
    148167{ 
    149168        MSSndCard *card = ms_snd_card_new(&ca_card_desc); 
     169        AudioStreamBasicDescription format; 
    150170        AuCard *d = (AuCard *) card->data; 
     171        unsigned int slen; 
     172        int err; 
     173 
    151174        d->uidname = ms_strdup(uidname); 
    152175        d->dev = dev; 
    153176        card->name = ms_strdup(name); 
    154177        card->capabilities = cap; 
     178         
     179        slen = sizeof(format); 
     180        d->rate=44100; 
     181        err = AudioDeviceGetProperty(dev, 0, cap & MS_SND_CARD_CAP_CAPTURE, kAudioDevicePropertyStreamFormat, &slen, &format); 
     182        if (err == kAudioHardwareNoError) { 
     183                show_format("output device", &format); 
     184                d->rate=format.mSampleRate; 
     185        } 
    155186        return card; 
    156 } 
    157  
    158 static void show_format(const char *name, AudioStreamBasicDescription * deviceFormat) 
    159 { 
    160         ms_message("Format for %s", name); 
    161         ms_message("mSampleRate = %g", deviceFormat->mSampleRate); 
    162         char *the4CCString = (char *) &deviceFormat->mFormatID; 
    163         char outName[5]; 
    164         outName[0] = the4CCString[0]; 
    165         outName[1] = the4CCString[1]; 
    166         outName[2] = the4CCString[2]; 
    167         outName[3] = the4CCString[3]; 
    168         outName[4] = 0; 
    169         ms_message("mFormatID = %s", outName); 
    170         ms_message("mFormatFlags = %08lX", deviceFormat->mFormatFlags); 
    171         ms_message("mBytesPerPacket = %ld", deviceFormat->mBytesPerPacket); 
    172         ms_message("mFramesPerPacket = %ld", deviceFormat->mFramesPerPacket); 
    173         ms_message("mChannelsPerFrame = %ld", deviceFormat->mChannelsPerFrame); 
    174         ms_message("mBytesPerFrame = %ld", deviceFormat->mBytesPerFrame); 
    175         ms_message("mBitsPerChannel = %ld", deviceFormat->mBitsPerChannel); 
    176187} 
    177188 
     
    222233        ms_message("CA: devname:%s uidname:%s", devname, uidname); 
    223234                         
    224         AudioStreamBasicDescription devicewriteFormat; 
    225         slen = sizeof(devicewriteFormat); 
    226         err = AudioDeviceGetProperty(id, 0, is_input, kAudioDevicePropertyStreamFormat, &slen, &devicewriteFormat); 
    227         if (err == kAudioHardwareNoError) { 
    228                 show_format("output device", &devicewriteFormat); 
    229         } 
     235         
    230236        return ret; 
    231237} 
     
    278284{ 
    279285        AURead *d=(AURead*)inRefCon; 
    280          
    281         CHECK_AURESULT(AudioUnitRender(d->common.au, inActionFlags, inTimeStamp, inBusNumber, 
    282                                                   inNumFrames, ioData)); 
    283         if( ioData==NULL) 
    284         { 
     286        AudioBufferList lreadAudioBufferList={0}; 
     287        mblk_t *rm; 
     288        OSStatus err; 
     289 
     290         
     291 
     292        lreadAudioBufferList.mNumberBuffers=1; 
     293        lreadAudioBufferList.mBuffers[0].mDataByteSize=inNumFrames*sizeof(int16_t)*d->common.nchannels; 
     294        rm=allocb(lreadAudioBufferList.mBuffers[0].mDataByteSize,0); 
     295        lreadAudioBufferList.mBuffers[0].mData=rm->b_wptr; 
     296        lreadAudioBufferList.mBuffers[0].mNumberChannels = 1; 
     297 
     298        //ms_message("request to render %i bytes, inNumFrames=%i",lreadAudioBufferList.mBuffers[0].mDataByteSize,inNumFrames); 
     299        err=AudioUnitRender(d->common.au, inActionFlags, inTimeStamp, inBusNumber, inNumFrames, &lreadAudioBufferList); 
     300         
     301        if (err!=noErr){ 
     302                ms_error("AudioUnitRender() for read returned [%i] %s %s",err,GetMacOSStatusErrorString(err),GetMacOSStatusCommentString(err)); 
    285303                return 0; 
    286304        } 
    287         ms_message("Got input buffer of size %i",ioData->mBuffers[0].mDataByteSize); 
    288         mblk_t *rm=NULL; 
    289         rm=allocb(ioData->mBuffers[0].mDataByteSize,0); 
    290         memcpy(rm->b_wptr, ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize); 
    291         rm->b_wptr+=ioData->mBuffers[0].mDataByteSize; 
     305        //ms_message("Got input buffer of size %i",lreadAudioBufferList.mBuffers[0].mDataByteSize); 
     306 
     307        rm->b_wptr+=lreadAudioBufferList.mBuffers[0].mDataByteSize; 
    292308         
    293309        ms_mutex_lock(&d->common.mutex); 
    294310        putq(&d->rq,rm); 
    295311        ms_mutex_unlock(&d->common.mutex); 
    296         rm=NULL; 
    297          
     312 
    298313        return 0; 
    299314} 
     
    306321                                                 AudioBufferList *ioData) 
    307322{ 
    308         OSStatus err= noErr; 
    309323        AUWrite *d=(AUWrite*)inRefCon; 
    310324        int read; 
     325 
     326        if (ioData->mNumberBuffers!=1) ms_warning("writeRenderProc: %i buffers",ioData->mNumberBuffers); 
    311327        ms_mutex_lock(&d->common.mutex); 
    312328        read=ms_bufferizer_read(d->buffer,ioData->mBuffers[0].mData,ioData->mBuffers[0].mDataByteSize); 
     
    315331                ms_warning("Silence inserted in audio output unit (%i bytes)",ioData->mBuffers[0].mDataByteSize); 
    316332                memset(ioData->mBuffers[0].mData,0,ioData->mBuffers[0].mDataByteSize); 
    317         } 
    318         err = AudioUnitRender(d->common.au, inActionFlags, inTimeStamp, inBusNumber,inNumFrames, ioData); 
    319         if(err != noErr){ 
    320                 ms_error("AudioUnitRender() failed for write: %i",err); 
    321333        } 
    322334        return 0; 
     
    375387                                  kAudioOutputUnitProperty_CurrentDevice, 
    376388                                  kAudioUnitScope_Global, 
    377                                   0, 
     389                                  output_bus, 
    378390                                  &d->dev, 
    379391                                  sizeof(AudioDeviceID))); 
    380392         
     393 
     394        param=0; 
     395        CHECK_AURESULT(AudioUnitSetProperty(d->au, 
     396                                          kAudioUnitProperty_ShouldAllocateBuffer, 
     397                                          is_read ? kAudioUnitScope_Input : kAudioUnitScope_Output , 
     398                                          is_read ? input_bus : output_bus , 
     399                                          &param, 
     400                                          sizeof(param))); 
     401 
    381402        UInt32 asbdsize = sizeof(AudioStreamBasicDescription); 
    382403        memset((char *)&asbd, 0, asbdsize); 
     
    390411         
    391412        show_format(is_read ? "Input audio unit" : "Output audio unit",&asbd); 
    392         if (asbd.mChannelsPerFrame>1) 
    393         { 
    394                 asbd.mBytesPerFrame = asbd.mBytesPerFrame / asbd.mChannelsPerFrame; 
    395                 asbd.mBytesPerPacket = asbd.mBytesPerPacket / asbd.mChannelsPerFrame;            
    396                 asbd.mChannelsPerFrame = 1; 
    397         } 
     413         
     414        asbd.mSampleRate=d->rate; 
     415                         
     416        asbd.mBytesPerPacket=asbd.mBytesPerFrame = 2*d->nchannels; 
     417        asbd.mChannelsPerFrame = d->nchannels; 
     418        asbd.mBitsPerChannel=16; 
     419        asbd.mFormatID=kAudioFormatLinearPCM; 
     420        asbd.mFormatFlags=kAudioFormatFlagIsPacked|kAudioFormatFlagIsSignedInteger; 
     421         
     422 
    398423         
    399424        CHECK_AURESULT(AudioUnitSetProperty(d->au, 
    400425                                          kAudioUnitProperty_StreamFormat, 
    401                                           is_read ? kAudioUnitScope_Input : kAudioUnitScope_Output , 
    402                                           is_read ? output_bus : input_bus , 
     426                                          is_read ?  kAudioUnitScope_Output : kAudioUnitScope_Input, 
     427                                          is_read ?  input_bus : output_bus , 
    403428                                          &asbd, 
    404429                                          sizeof(AudioStreamBasicDescription))); 
     430        CHECK_AURESULT(AudioUnitGetProperty(d->au, 
     431                           kAudioUnitProperty_StreamFormat, 
     432                           is_read ? kAudioUnitScope_Output : kAudioUnitScope_Input, 
     433                           is_read ? input_bus : output_bus , 
     434                           &asbd, 
     435                           &asbdsize)); 
     436         
     437        show_format(is_read ? "Input audio unit after configuration" : "Output audio unit after configuration",&asbd); 
     438 
    405439         
    406440        // Get the number of frames in the IO buffer(s) 
    407441        param = sizeof(UInt32); 
    408         UInt32 fAudioSamples; 
     442        UInt32 numFrames; 
    409443        CHECK_AURESULT(AudioUnitGetProperty(d->au, 
    410444                                          kAudioDevicePropertyBufferFrameSize, 
    411445                                          kAudioUnitScope_Input, 
    412                                           1, 
    413                                           &fAudioSamples, 
     446                                          input_bus, 
     447                                          &numFrames, 
    414448                                          &param)); 
    415          
    416         result = AudioUnitInitialize(d->au); 
    417         if(result != noErr) 
    418         { 
    419                 ms_error("failed to AudioUnitInitialize input %i", result); 
    420                 return -1; 
    421         } 
     449        ms_message("Number of frames per buffer = %i", numFrames); 
     450         
    422451        AURenderCallbackStruct cbs; 
    423452         
     
    428457                                        kAudioOutputUnitProperty_SetInputCallback, 
    429458                                        kAudioUnitScope_Global, 
    430                                         0, 
     459                                        input_bus, 
    431460                                        &cbs, 
    432461                                        sizeof(AURenderCallbackStruct))); 
     
    435464                CHECK_AURESULT(AudioUnitSetProperty (d->au,  
    436465                            kAudioUnitProperty_SetRenderCallback,  
    437                             kAudioUnitScope_Input,  
    438                             0, 
     466                            kAudioUnitScope_Global,  
     467                            output_bus, 
    439468                            &cbs,  
    440469                            sizeof(AURenderCallbackStruct))); 
     470        } 
     471        result = AudioUnitInitialize(d->au); 
     472        if(result != noErr) 
     473        { 
     474                ms_error("failed to AudioUnitInitialize %i , is_read=%i", result,(int)is_read); 
     475                return -1; 
    441476        } 
    442477 
     
    468503 
    469504static void au_common_init(AUCommon *d){ 
    470         d->rate=8000; 
     505        d->rate=44100; 
    471506        d->nchannels=1; 
    472507        ms_mutex_init(&d->mutex,NULL); 
     
    545580static int set_rate(MSFilter *f, void *arg){ 
    546581        AUCommon *d = (AUCommon *) f->data; 
    547         d->rate = *((int *) arg); 
    548         return 0; 
     582        /*the hal audio unit does not accept custom rates*/ 
     583        return (d->rate==*(int*)arg) ? 0 : -1; 
    549584} 
    550585 
     
    604639        AURead *d = (AURead *) f->data; 
    605640        d->common.dev = wc->dev; 
     641        d->common.rate=wc->rate; 
    606642        return f; 
    607643} 
     
    613649        AUWrite *d = (AUWrite *) f->data; 
    614650        d->common.dev = wc->dev; 
     651        d->common.rate=wc->rate; 
    615652        return f; 
    616653} 
Note: See TracChangeset for help on using the changeset viewer.