00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00031 #include "stdinc.h"
00032
00033 #include <CoreAudio/AudioHardware.h>
00034
00035 #include "audio_file.h"
00036 #include "audio_output.h"
00037 #include "gui.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00055 AudioDeviceID adid;
00059 AudioStreamBasicDescription afmt;
00060 #ifdef MAC_OS_X_VERSION_10_5
00061
00064 AudioDeviceIOProcID aprocid;
00065 #else
00066 #define aprocid audio_output_ioproc
00067 #endif
00068
00073 int16_t *abufnew;
00077 int16_t *abufcur;
00081 int abuflen;
00086 int abufulen = 0;
00091 GMutex *abuflock;
00096 GCond *abufdrained;
00097 #ifdef BUILD_VOLUME
00098
00102 UInt32 achans[2] = { 0, 0 };
00103 #endif
00104
00109 static OSStatus
00110 audio_output_ioproc(AudioDeviceID inDevice, const AudioTimeStamp *inNow,
00111 const AudioBufferList *inInputData, const AudioTimeStamp *inInputTime,
00112 AudioBufferList *outOutputData, const AudioTimeStamp *inOutputTime,
00113 void *inClientData)
00114 {
00115 int i, len;
00116 float *ob = outOutputData->mBuffers[0].mData;
00117
00118
00119 len = g_atomic_int_get(&abufulen);
00120 if (len == 0)
00121 AudioDeviceStop(adid, aprocid);
00122
00123
00124 for (i = 0; i < len; i++)
00125 ob[i] = (float)abufcur[i] / SHRT_MAX;
00126
00127
00128 g_atomic_int_set(&abufulen, 0);
00129 g_cond_signal(abufdrained);
00130
00131
00132 for (; i < abuflen; i++)
00133 ob[i] = 0.0;
00134
00135 return (0);
00136 }
00137
00138 int
00139 audio_output_open(void)
00140 {
00141 UInt32 size;
00142
00143
00144 size = sizeof adid;
00145 if (AudioHardwareGetProperty(
00146 kAudioHardwarePropertyDefaultOutputDevice,
00147 &size, &adid) != 0 || adid == kAudioDeviceUnknown)
00148 goto error;
00149
00150
00151 size = sizeof afmt;
00152 if (AudioDeviceGetProperty(adid, 0, false,
00153 kAudioDevicePropertyStreamFormat, &size, &afmt) != 0 ||
00154 afmt.mFormatID != kAudioFormatLinearPCM)
00155 goto error;
00156
00157
00158 afmt.mSampleRate = 0;
00159 afmt.mChannelsPerFrame = 0;
00160 afmt.mBytesPerFrame = afmt.mChannelsPerFrame * sizeof (float);
00161 afmt.mBytesPerPacket = afmt.mBytesPerFrame * afmt.mFramesPerPacket;
00162
00163
00164 size = sizeof abuflen;
00165 abuflen = 32768;
00166 AudioDeviceSetProperty(adid, 0, 0, false,
00167 kAudioDevicePropertyBufferSize, size, &abuflen);
00168 if (AudioDeviceGetProperty(adid, 0, false,
00169 kAudioDevicePropertyBufferSize, &size, &abuflen) != 0)
00170 goto error;
00171
00172 #ifdef BUILD_VOLUME
00173
00174 size = sizeof achans;
00175 AudioDeviceGetProperty(adid, 0, false,
00176 kAudioDevicePropertyPreferredChannelsForStereo, &size, &achans);
00177 #endif
00178
00179
00180 abuflen /= sizeof(float);
00181 abufnew = g_malloc(abuflen * sizeof(int16_t));
00182 abufcur = g_malloc(abuflen * sizeof(int16_t));
00183
00184
00185 abuflock = g_mutex_new();
00186 abufdrained = g_cond_new();
00187
00188
00189 #ifdef MAC_OS_X_VERSION_10_5
00190 if (AudioDeviceCreateIOProcID(adid, audio_output_ioproc, NULL,
00191 &aprocid) != 0)
00192 #else
00193 if (AudioDeviceAddIOProc(adid, audio_output_ioproc, NULL) != 0)
00194 #endif
00195 goto error;
00196
00197 return (0);
00198 error:
00199 g_printerr("%s\n", _("Cannot open the audio device."));
00200 return (-1);
00201 }
00202
00203 int
00204 audio_output_play(struct audio_file *fd)
00205 {
00206 UInt32 len, size;
00207 int16_t *tmp;
00208
00209
00210 if ((len = audio_file_read(fd, abufnew, abuflen)) == 0)
00211 return (-1);
00212
00213 if (fd->srate != afmt.mSampleRate ||
00214 fd->channels != afmt.mChannelsPerFrame) {
00215
00216 afmt.mSampleRate = fd->srate;
00217 afmt.mChannelsPerFrame = fd->channels;
00218
00219 if (AudioDeviceSetProperty(adid, 0, 0, 0,
00220 kAudioDevicePropertyStreamFormat, sizeof afmt, &afmt) != 0) {
00221
00222 size = sizeof afmt;
00223 AudioDeviceGetProperty(adid, 0, false,
00224 kAudioDevicePropertyStreamFormat, &size, &afmt);
00225
00226 gui_msgbar_warn(_("Sample rate or amount of channels not supported."));
00227 return (-1);
00228 }
00229 }
00230
00231
00232 g_mutex_lock(abuflock);
00233 while (g_atomic_int_get(&abufulen) != 0)
00234 g_cond_wait(abufdrained, abuflock);
00235 g_mutex_unlock(abuflock);
00236
00237
00238 tmp = abufcur;
00239 abufcur = abufnew;
00240 abufnew = tmp;
00241
00242
00243 g_atomic_int_set(&abufulen, len);
00244
00245
00246 AudioDeviceStart(adid, aprocid);
00247
00248 return (0);
00249 }
00250
00251 void
00252 audio_output_close(void)
00253 {
00254 AudioDeviceStop(adid, aprocid);
00255 #ifdef MAC_OS_X_VERSION_10_5
00256 AudioDeviceDestroyIOProcID(adid, aprocid);
00257 #else
00258 AudioDeviceRemoveIOProc(adid, aprocid);
00259 #endif
00260
00261 g_free(abufnew);
00262 g_free(abufcur);
00263 }
00264
00265 #ifdef BUILD_VOLUME
00266
00270 static int
00271 audio_output_volume_adjust(Float32 n)
00272 {
00273 Float32 vl, vr, vn;
00274 UInt32 size = sizeof vl;
00275
00276
00277
00278
00279
00280
00281
00282 if (AudioDeviceGetProperty(adid, achans[0], false,
00283 kAudioDevicePropertyVolumeScalar, &size, &vl) != 0 ||
00284 AudioDeviceGetProperty(adid, achans[1], false,
00285 kAudioDevicePropertyVolumeScalar, &size, &vr) != 0)
00286 return (-1);
00287 vn = CLAMP((vl + vr) / 2.0 + n, 0.0, 1.0);
00288
00289
00290 if (AudioDeviceSetProperty(adid, 0, achans[0], false,
00291 kAudioDevicePropertyVolumeScalar, size, &vn) != 0 ||
00292 AudioDeviceSetProperty(adid, 0, achans[1], false,
00293 kAudioDevicePropertyVolumeScalar, size, &vn) != 0)
00294 return (-1);
00295
00296 return (vn * 100.0);
00297 }
00298
00299 int
00300 audio_output_volume_up(void)
00301 {
00302 return audio_output_volume_adjust(0.04);
00303 }
00304
00305 int
00306 audio_output_volume_down(void)
00307 {
00308 return audio_output_volume_adjust(-0.04);
00309 }
00310 #endif