aboutsummaryrefslogtreecommitdiffhomepage
path: root/libao2
diff options
context:
space:
mode:
authorGravatar arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2005-01-01 03:51:08 +0000
committerGravatar arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2005-01-01 03:51:08 +0000
commitf18153ca99d3ac5dce29dbb6f7e05458d124ebac (patch)
treeea26cda02a20d803de0b7e36684adb34775f18ec /libao2
parent4296d7b60308b96fe1d94d045136bb8b517e79a6 (diff)
rate/format matching and volume get/set support
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@14291 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libao2')
-rw-r--r--libao2/ao_macosx.c179
1 files changed, 151 insertions, 28 deletions
diff --git a/libao2/ao_macosx.c b/libao2/ao_macosx.c
index 8ab0ab2b3c..f8e11d18e0 100644
--- a/libao2/ao_macosx.c
+++ b/libao2/ao_macosx.c
@@ -64,7 +64,7 @@ LIBAO_EXTERN(macosx)
/* This is large, but best (maybe it should be even larger).
* CoreAudio supposedly has an internal latency in the order of 2ms */
-#define NUM_BUFS 16
+#define NUM_BUFS 32
typedef struct ao_macosx_s
{
@@ -163,13 +163,42 @@ static OSStatus audioDeviceIOProc(AudioDeviceID inDevice, const AudioTimeStamp *
static int control(int cmd,void *arg){
+ OSStatus status;
+ UInt32 propertySize;
+ ao_control_vol_t* vol = (ao_control_vol_t*)arg;
+ UInt32 stereoChannels[2];
+ static float volume=0.5;
switch (cmd) {
case AOCONTROL_SET_DEVICE:
case AOCONTROL_GET_DEVICE:
- case AOCONTROL_GET_VOLUME:
- case AOCONTROL_SET_VOLUME:
/* unimplemented/meaningless */
return CONTROL_FALSE;
+ case AOCONTROL_GET_VOLUME:
+ propertySize=sizeof(stereoChannels);
+ status = AudioDeviceGetProperty(ao->outputDeviceID, NULL, 0,
+ kAudioDevicePropertyPreferredChannelsForStereo, &propertySize,
+ &stereoChannels);
+// printf("OSX: stereochannels %d ; %d \n",stereoChannels[0],stereoChannels[1]);
+ propertySize=sizeof(volume);
+ status = AudioDeviceGetProperty(ao->outputDeviceID, stereoChannels[0], false, kAudioDevicePropertyVolumeScalar, &propertySize, &volume);
+// printf("OSX: get volume=%5.3f status=%d \n",volume,status);
+ vol->left=(int)(volume*100.0);
+ status = AudioDeviceGetProperty(ao->outputDeviceID, stereoChannels[1], false, kAudioDevicePropertyVolumeScalar, &propertySize, &volume);
+ vol->right=(int)(volume*100.0);
+ return CONTROL_TRUE;
+ case AOCONTROL_SET_VOLUME:
+ propertySize=sizeof(stereoChannels);
+ status = AudioDeviceGetProperty(ao->outputDeviceID, NULL, 0,
+ kAudioDevicePropertyPreferredChannelsForStereo, &propertySize,
+ &stereoChannels);
+// printf("OSX: stereochannels %d ; %d \n",stereoChannels[0],stereoChannels[1]);
+ propertySize=sizeof(volume);
+ volume=vol->left/100.0;
+ status = AudioDeviceSetProperty(ao->outputDeviceID, 0, stereoChannels[0], 0, kAudioDevicePropertyVolumeScalar, propertySize, &volume);
+// printf("OSX: set volume=%5.3f status=%d\n",volume,status);
+ volume=vol->right/100.0;
+ status = AudioDeviceSetProperty(ao->outputDeviceID, 0, stereoChannels[1], 0, kAudioDevicePropertyVolumeScalar, propertySize, &volume);
+ return CONTROL_TRUE;
case AOCONTROL_QUERY_FORMAT:
/* stick with what CoreAudio requests */
return CONTROL_FALSE;
@@ -180,6 +209,33 @@ static int control(int cmd,void *arg){
}
+static void print_format(AudioStreamBasicDescription *f){
+ uint32_t flags=(uint32_t) f->mFormatFlags;
+ ao_msg(MSGT_AO,MSGL_INFO, "hw-format: %7.1fHz %dbit [%c%c%c%c] %s %s %s%s%s%s\n",
+ f->mSampleRate, f->mBitsPerChannel,
+ (int)(f->mFormatID & 0xff000000) >> 24,
+ (int)(f->mFormatID & 0x00ff0000) >> 16,
+ (int)(f->mFormatID & 0x0000ff00) >> 8,
+ (int)(f->mFormatID & 0x000000ff) >> 0,
+ (flags&kAudioFormatFlagIsFloat) ? "float" : "int",
+ (flags&kAudioFormatFlagIsBigEndian) ? "BE" : "LE",
+ (flags&kAudioFormatFlagIsSignedInteger) ? "S" : "U",
+ (flags&kAudioFormatFlagIsPacked) ? " packed" : "",
+ (flags&kAudioFormatFlagIsAlignedHigh) ? " aligned" : "",
+ (flags&kAudioFormatFlagIsNonInterleaved) ? " ni" : "" );
+
+ ao_msg(MSGT_AO,MSGL_V, "%5d mBytesPerPacket\n",
+ (int)f->mBytesPerPacket);
+ ao_msg(MSGT_AO,MSGL_V, "%5d mFramesPerPacket\n",
+ (int)f->mFramesPerPacket);
+ ao_msg(MSGT_AO,MSGL_V, "%5d mBytesPerFrame\n",
+ (int)f->mBytesPerFrame);
+ ao_msg(MSGT_AO,MSGL_V, "%5d mChannelsPerFrame\n",
+ (int)f->mChannelsPerFrame);
+
+}
+
+
static int init(int rate,int channels,int format,int flags)
{
OSStatus status;
@@ -207,34 +263,102 @@ static int init(int rate,int channels,int format,int flags)
ao_msg(MSGT_AO,MSGL_WARN, "AudioHardwareGetProperty: ao->outputDeviceID is kAudioDeviceUnknown\n");
return CONTROL_FALSE;
}
+
+
+#if 0
+// dump supported format list:
+{ AudioStreamBasicDescription* p;
+ Boolean ow;
+ int i;
+ propertySize=0; //sizeof(p);
+ status = AudioDeviceGetPropertyInfo(ao->outputDeviceID, 0, true, kAudioStreamPropertyPhysicalFormats, &propertySize, &ow);
+// status = AudioDeviceGetPropertyInfo(ao->outputDeviceID, 0, true, kAudioDevicePropertyStreamFormats, &propertySize, &ow);
+ if (status) {
+ ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceGetPropertyInfo returned 0x%X when getting kAudioDevicePropertyStreamFormats\n", (int)status);
+ }
+ p=malloc(propertySize);
+// printf("propertySize=%d\n",propertySize);
+ status = AudioDeviceGetProperty(ao->outputDeviceID, 0, true, kAudioStreamPropertyPhysicalFormats, &propertySize, p);
+// status = AudioDeviceGetProperty(ao->outputDeviceID, 0, true, 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(&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:
+ 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_F){
+ // float
+ ao->outputStreamBasicDescription.mFormatFlags=kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked;
+ } else if(format&AF_FORMAT_SI){
+ // signed int
+ ao->outputStreamBasicDescription.mFormatFlags=kAudioFormatFlagIsSignedInteger|kAudioFormatFlagIsPacked;
+ } else {
+ // unsigned int
+ ao->outputStreamBasicDescription.mFormatFlags=kAudioFormatFlagIsPacked;
+ }
+ if(format&AF_FORMAT_BE)
+ ao->outputStreamBasicDescription.mFormatFlags|=kAudioFormatFlagIsBigEndian;
+
+ ao->outputStreamBasicDescription.mBytesPerPacket=
+ ao->outputStreamBasicDescription.mBytesPerFrame=channels*(ao->outputStreamBasicDescription.mBitsPerChannel/8);
+ ao->outputStreamBasicDescription.mFramesPerPacket=1;
+
+// print_format(&ao->outputStreamBasicDescription);
+
+// propertySize = sizeof(ao->outputStreamBasicDescription);
+// status = AudioDeviceGetProperty(ao->outputDeviceID, 0, true, kAudioDevicePropertyStreamFormatSupported, &propertySize, &ao->outputStreamBasicDescription);
+// if (status) {
+// ao_msg(MSGT_AO,MSGL_V, "AudioDeviceGetProperty returned 0x%X when getting kAudioDevicePropertyStreamFormatSupported\n", (int)status);
+// }
- /* get default output format
- * TODO: get all support formats and iterate through them
- */
+// status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormat, &propertySize, &ao->outputStreamBasicDescription);
propertySize = sizeof(ao->outputStreamBasicDescription);
- status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormat, &propertySize, &ao->outputStreamBasicDescription);
- if (status) {
- ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceGetProperty returned %d when getting kAudioDevicePropertyStreamFormat\n", (int)status);
- return CONTROL_FALSE;
+ status = AudioDeviceGetProperty(ao->outputDeviceID, 0, true, 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, true, 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, 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;
+ }
+ }
}
- ao_msg(MSGT_AO,MSGL_V, "hardware format...\n");
- ao_msg(MSGT_AO,MSGL_V, "%f mSampleRate\n", ao->outputStreamBasicDescription.mSampleRate);
- ao_msg(MSGT_AO,MSGL_V, " %c%c%c%c mFormatID\n",
- (int)(ao->outputStreamBasicDescription.mFormatID & 0xff000000) >> 24,
- (int)(ao->outputStreamBasicDescription.mFormatID & 0x00ff0000) >> 16,
- (int)(ao->outputStreamBasicDescription.mFormatID & 0x0000ff00) >> 8,
- (int)(ao->outputStreamBasicDescription.mFormatID & 0x000000ff) >> 0);
- ao_msg(MSGT_AO,MSGL_V, "%5d mBytesPerPacket\n",
- (int)ao->outputStreamBasicDescription.mBytesPerPacket);
- ao_msg(MSGT_AO,MSGL_V, "%5d mFramesPerPacket\n",
- (int)ao->outputStreamBasicDescription.mFramesPerPacket);
- ao_msg(MSGT_AO,MSGL_V, "%5d mBytesPerFrame\n",
- (int)ao->outputStreamBasicDescription.mBytesPerFrame);
- ao_msg(MSGT_AO,MSGL_V, "%5d mChannelsPerFrame\n",
- (int)ao->outputStreamBasicDescription.mChannelsPerFrame);
+ print_format(&ao->outputStreamBasicDescription);
/* get requested buffer length */
+ // TODO: set NUM_BUFS dinamically, based on buffer size!
propertySize = sizeof(ao->buffer_len);
status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyBufferSize, &propertySize, &ao->buffer_len);
if (status) {
@@ -252,11 +376,10 @@ static int init(int rate,int channels,int format,int flags)
if (ao->outputStreamBasicDescription.mFormatID == kAudioFormatLinearPCM) {
uint32_t flags = ao->outputStreamBasicDescription.mFormatFlags;
if (flags & kAudioFormatFlagIsFloat) {
- ao_data.format = AF_FORMAT_FLOAT_NE;
+ ao_data.format = (flags&kAudioFormatFlagIsBigEndian) ? AF_FORMAT_FLOAT_BE : AF_FORMAT_FLOAT_LE;
} else {
ao_msg(MSGT_AO,MSGL_WARN, "Unsupported audio output "
- "format %d. Please report this to the developer\n",
- (int)status);
+ "format 0x%X. Please report this to the developer\n", format);
return CONTROL_FALSE;
}