📄 ao_macosx.c
字号:
ao_msg(MSGT_AO,MSGL_WARN, "AudioHardwareGetProperty returned %d\n", (int)status); return CONTROL_FALSE; } if (ao->outputDeviceID == kAudioDeviceUnknown) { ao_msg(MSGT_AO,MSGL_WARN, "AudioHardwareGetProperty: ao->outputDeviceID is kAudioDeviceUnknown\n"); return CONTROL_FALSE; } propertySize = sizeof(ao->outputStreamBasicDescription); status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormat, &propertySize, &ao->outputStreamBasicDescription); if(!status) print_format("default:",&ao->outputStreamBasicDescription);#if 1// dump supported format list:{ AudioStreamBasicDescription* p; Boolean ow; int i; propertySize=0; //sizeof(p);// status = AudioDeviceGetPropertyInfo(ao->outputDeviceID, 0, false, kAudioStreamPropertyPhysicalFormats, &propertySize, &ow); status = AudioDeviceGetPropertyInfo(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormats, &propertySize, &ow); if (status) { ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceGetPropertyInfo returned 0x%X when getting kAudioDevicePropertyStreamFormats\n", (int)status); } p=malloc(propertySize);// status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioStreamPropertyPhysicalFormats, &propertySize, p); status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormats, &propertySize, p); if (status) { ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceGetProperty returned 0x%X when getting kAudioDevicePropertyStreamFormats\n", (int)status);// return CONTROL_FALSE; } for(i=0;i<propertySize/sizeof(AudioStreamBasicDescription);i++) print_format("support:",&p[i]);// printf("FORMATS: (%d) %p %p %p %p\n",propertySize,p[0],p[1],p[2],p[3]); free(p);}#endif // fill in our wanted format, and let's see if the driver accepts it or // offers some similar alternative: propertySize = sizeof(ao->outputStreamBasicDescription); memset(&ao->outputStreamBasicDescription,0,propertySize); ao->outputStreamBasicDescription.mSampleRate=rate; ao->outputStreamBasicDescription.mFormatID=kAudioFormatLinearPCM; ao->outputStreamBasicDescription.mChannelsPerFrame=channels; switch(format&AF_FORMAT_BITS_MASK){ case AF_FORMAT_8BIT: ao->outputStreamBasicDescription.mBitsPerChannel=8; break; case AF_FORMAT_16BIT: ao->outputStreamBasicDescription.mBitsPerChannel=16; break; case AF_FORMAT_24BIT: ao->outputStreamBasicDescription.mBitsPerChannel=24; break; case AF_FORMAT_32BIT: ao->outputStreamBasicDescription.mBitsPerChannel=32; break; } if((format&AF_FORMAT_POINT_MASK)==AF_FORMAT_F){ // float ao->outputStreamBasicDescription.mFormatFlags=kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked; } else if((format&AF_FORMAT_SIGN_MASK)==AF_FORMAT_SI){ // signed int ao->outputStreamBasicDescription.mFormatFlags=kAudioFormatFlagIsSignedInteger|kAudioFormatFlagIsPacked; } else { // unsigned int ao->outputStreamBasicDescription.mFormatFlags=kAudioFormatFlagIsPacked; } if((format&AF_FORMAT_END_MASK)==AF_FORMAT_BE) ao->outputStreamBasicDescription.mFormatFlags|=kAudioFormatFlagIsBigEndian; ao->outputStreamBasicDescription.mBytesPerPacket= ao->outputStreamBasicDescription.mBytesPerFrame=channels*(ao->outputStreamBasicDescription.mBitsPerChannel/8); ao->outputStreamBasicDescription.mFramesPerPacket=1; print_format("wanted: ",&ao->outputStreamBasicDescription); // try 1: ask if it accepts our specific requirements? propertySize = sizeof(ao->outputStreamBasicDescription);// status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioStreamPropertyPhysicalFormatMatch, &propertySize, &ao->outputStreamBasicDescription); status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormatMatch, &propertySize, &ao->outputStreamBasicDescription); if (status || ao->outputStreamBasicDescription.mSampleRate!=rate || ao->outputStreamBasicDescription.mFormatID!=kAudioFormatLinearPCM) { ao_msg(MSGT_AO,MSGL_V, "AudioDeviceGetProperty returned 0x%X when getting kAudioDevicePropertyStreamFormatMatch\n", (int)status); // failed (error, bad rate or bad type) // try 2: set only rate & type, no format details (bits, channels etc) propertySize = sizeof(ao->outputStreamBasicDescription); memset(&ao->outputStreamBasicDescription,0,propertySize); ao->outputStreamBasicDescription.mSampleRate=rate; ao->outputStreamBasicDescription.mFormatID=kAudioFormatLinearPCM;// status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioStreamPropertyPhysicalFormatMatch, &propertySize, &ao->outputStreamBasicDescription); status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormatMatch, &propertySize, &ao->outputStreamBasicDescription); if (status || ao->outputStreamBasicDescription.mFormatID!=kAudioFormatLinearPCM) { ao_msg(MSGT_AO,MSGL_V, "AudioDeviceGetProperty returned 0x%X when getting kAudioDevicePropertyStreamFormatMatch\n", (int)status); // failed again. (error or bad type) // giving up... just read the default. propertySize = sizeof(ao->outputStreamBasicDescription);// status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioStreamPropertyPhysicalFormat, &propertySize, &ao->outputStreamBasicDescription); status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormat, &propertySize, &ao->outputStreamBasicDescription); if (status) { // failed to read the default format - WTF? ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceGetProperty returned 0x%X when getting kAudioDevicePropertyStreamFormat\n", (int)status); return CONTROL_FALSE; } } }// propertySize = sizeof(ao->outputStreamBasicDescription);// status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormatSupported, &propertySize, &ao->outputStreamBasicDescription);// if (status) {// ao_msg(MSGT_AO,MSGL_V, "AudioDeviceGetProperty returned 0x%X when getting kAudioDevicePropertyStreamFormatSupported\n", (int)status);// } // ok, now try to set the new (default or matched) audio format: print_format("best: ",&ao->outputStreamBasicDescription); propertySize = sizeof(ao->outputStreamBasicDescription); status = AudioDeviceSetProperty(ao->outputDeviceID, 0, 0, false, kAudioDevicePropertyStreamFormat, propertySize, &ao->outputStreamBasicDescription); if(status) ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceSetProperty returned 0x%X when getting kAudioDevicePropertyStreamFormat\n", (int)status); // see what did we get finally... we'll be forced to use this anyway :( propertySize = sizeof(ao->outputStreamBasicDescription); status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormat, &propertySize, &ao->outputStreamBasicDescription); print_format("final: ",&ao->outputStreamBasicDescription); /* get requested buffer length */ // TODO: set NUM_BUFS dinamically, based on buffer size! propertySize = sizeof(ao->chunk_size); status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyBufferSize, &propertySize, &ao->chunk_size); if (status) { ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceGetProperty returned %d when getting kAudioDevicePropertyBufferSize\n", (int)status); return CONTROL_FALSE; } ao_msg(MSGT_AO,MSGL_V, "%5d chunk size\n", (int)ao->chunk_size); ao_data.samplerate = ao->outputStreamBasicDescription.mSampleRate; ao_data.channels = channels; ao_data.outburst = ao_data.buffersize = ao->chunk_size; ao_data.bps = ao_data.samplerate * ao->outputStreamBasicDescription.mBytesPerFrame; if (ao->outputStreamBasicDescription.mFormatID == kAudioFormatLinearPCM) { uint32_t flags = ao->outputStreamBasicDescription.mFormatFlags; if (flags & kAudioFormatFlagIsFloat) { ao_data.format = (flags&kAudioFormatFlagIsBigEndian) ? AF_FORMAT_FLOAT_BE : AF_FORMAT_FLOAT_LE; } else { ao_msg(MSGT_AO,MSGL_WARN, "Unsupported audio output " "format 0x%X. Please report this to the developer\n", format); return CONTROL_FALSE; } } else { /* TODO: handle AFMT_AC3, AFMT_MPEG & friends */ ao_msg(MSGT_AO,MSGL_WARN, "Default Audio Device doesn't " "support Linear PCM!\n"); return CONTROL_FALSE; } /* Allocate ring-buffer memory */ ao->num_chunks = NUM_BUFS; ao->buffer_len = (ao->num_chunks + 1) * ao->chunk_size; ao->buffer = (unsigned char *)malloc(ao->buffer_len); /* Prepare for playback */ /* Set the IO proc that CoreAudio will call when it needs data */ status = AudioDeviceAddIOProc(ao->outputDeviceID, audioDeviceIOProc, NULL); if (status) { ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceAddIOProc returned %d\n", (int)status); return CONTROL_FALSE; } /* Start callback */ reset(); return CONTROL_OK;}static int play(void* output_samples,int num_bytes,int flags){ return write_buffer(output_samples, num_bytes);}/* set variables and buffer to initial state */static void reset(){ audio_pause(); /* reset ring-buffer state */ ao->buf_read_pos=0; ao->buf_write_pos=0; audio_resume(); return;}/* return available space */static int get_space(){ return buf_free();}/* return delay until audio is played */static float get_delay(){ int buffered = ao->buffer_len - ao->chunk_size - buf_free(); // could be less // inaccurate, should also contain the data buffered e.g. by the OS return (float)(buffered)/(float)ao_data.bps;}/* unload plugin and deregister from coreaudio */static void uninit(int immed){ int i; OSErr status; reset(); status = AudioDeviceRemoveIOProc(ao->outputDeviceID, audioDeviceIOProc); if (status) ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceRemoveIOProc " "returned %d\n", (int)status); free(ao->buffer); free(ao);}/* stop playing, keep buffers (for pause) */static void audio_pause(){ OSErr status; /* stop callback */ status = AudioDeviceStop(ao->outputDeviceID, audioDeviceIOProc); if (status) ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceStop returned %d\n", (int)status);}/* resume playing, after audio_pause() */static void audio_resume(){ OSErr status = AudioDeviceStart(ao->outputDeviceID, audioDeviceIOProc); if (status) ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceStart returned %d\n", (int)status);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -