/* * Copyright (C) 2004-2005 Vadim Berezniker * http://www.kryptolus.com * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include #include #include #include "kry_marker.h" #include "sound.h" #include "sound_out.h" #include "gui_main_audio.h" void soundserver_fill(struct sound_play_data *data); void mySoundProc(void *pSoundBuffer,long bufferLen); void soundserver_close(void); static USER_CALLBACK m_pUserCallback = NULL; static gboolean m_soundserver_mute[2]; static AudioUnit soundOutU; static int bufsize = 512; static unsigned char *buffer; static unsigned char playbackIsFinished = 0; static signed char closed = -1; static OSStatus myAURenderCallback (void *inRefCon, AudioUnitRenderActionFlags * ioActionFlags, const AudioTimeStamp * inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData) { struct sound_play_data *info = (struct sound_play_data*)inRefCon; int packetsize = info->sfinfo->channels*2; if (playbackIsFinished) return noErr; ioData->mBuffers[0].mNumberChannels = info->sfinfo->channels; if (packetsize * inNumberFrames > bufsize) { buffer = (unsigned char*)realloc (buffer, packetsize * inNumberFrames); bufsize = packetsize * inNumberFrames; } int rdsize = m_pUserCallback(buffer,inNumberFrames*packetsize,info); /* XXX muting isn't done (although who cares about it?)*/ if (rdsize == 0) goto alldone; ioData->mBuffers[0].mData = buffer; ioData->mBuffers[0].mDataByteSize = rdsize; return noErr; alldone: ; gui_main_audio_play_mode(SOUND_NOT_PLAYING); playbackIsFinished = 1; ioData->mBuffers[0].mDataByteSize = 0; AudioOutputUnitStop(soundOutU); return noErr; } int soundserver_open(USER_CALLBACK pUserCallback, int channels, int samplerate) { playbackIsFinished = 0; if (closed == 0) soundserver_close(); closed = 0; int stereo = (channels == 2); AudioStreamBasicDescription inFormat; size_t s = sizeof (inFormat); inFormat = (AudioStreamBasicDescription) { samplerate, kAudioFormatLinearPCM, kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked, stereo ? 4 : 2, 1, stereo ? 4 : 2, stereo ? 2 : 1, 16, 0 }; AudioUnitSetProperty (soundOutU, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &inFormat, s); m_pUserCallback = pUserCallback; return TRUE; } void soundserver_close(void) { if (closed != 0) return; closed = 1; playbackIsFinished = 1; AudioOutputUnitStop(soundOutU); } void soundserver_stop() { if (closed != 0) return; playbackIsFinished = 1; AudioOutputUnitStop(soundOutU); } void soundserver_init() { buffer = (unsigned char*) malloc (4096); ComponentDescription desc = { kAudioUnitType_Output, kAudioUnitSubType_DefaultOutput, 0, 0, 0 }; Component c = FindNextComponent (NULL, &desc); OpenAComponent (c, &soundOutU); AudioUnitInitialize (soundOutU); } void soundserver_mute(int channel) { m_soundserver_mute[channel] = 1; } void soundserver_play(struct sound_play_data *data) { if (closed != 0) return; AURenderCallbackStruct callbackSetup; callbackSetup.inputProc = myAURenderCallback; callbackSetup.inputProcRefCon = data; soundserver_stop(); playbackIsFinished = 0; AudioUnitSetProperty (soundOutU, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callbackSetup, sizeof (callbackSetup)); AudioOutputUnitStart(soundOutU); } enum sound_position_type soundserver_get_position_type() { return POSITION_AUTOMATIC; } enum soundserver_position_rv soundserver_get_position(int *pos) { return SOUNDSERVER_ERROR; }