/* * RageSoundDriver_QT.cpp * stepmania * * Created by Steve Checkoway on Mon Jun 23 2003. * Copyright (c) 2003 Steve Checkoway. All rights reserved. * */ #include "global.h" #include "RageSoundDriver_QT.h" #include "RageLog.h" #include "RageUtil.h" #include "RageLog.h" #include #include /* Ugh */ using namespace QT; const unsigned channels = 2; const unsigned samplesize = channels*16; const unsigned samples = 512; const unsigned freq = 44100; const unsigned buffersize = samples*samplesize/8; /* Oh boy! dealing with memory at inturupt time. What fun! */ #pragma options align=power static volatile Uint32 fill_me = 0; static UInt8 *buffer[2]; static CmpSoundHeader header; RageSound_QT::RageSound_QT() { RageException::ThrowNonfatal("Class not finished!"); /*SndCallBackUPP callback; callback = NewSndCallBackUPP(GetData); memset(&header, 0, sizeof(header)); header.numChannels = channels; header.sampleSize = samplesize / channels; header.sampleRate = rate44khz; /* really 44.1kHz * / header.numFrames = samples; header.encode = cmpSH; buffer[0] = new Uint8[buffersize]; buffer[1] = new Uint8[buffersize]; memset(buffer[0], 0, buffersize); memset(buffer[1], 0, buffersize); channel = new SndChannel; channel->userInfo = reinterpret_cast(this); channel->qLength = 2; soundOutput = OpenDefaultComponent(kSoundOutputDeviceType, NULL); ASSERT(soundOutput != NULL); TimeRecord record; SoundComponentGetInfo(soundOutput, NULL, siOutputLatency, &record); latency = record.value.lo / record.scale; latency += samples / freq; /* double buffer * / OSErr err = SndNewChannel(&channel, sampledSynth, initStereo, callback); if (err != noErr) { delete channel; channel = NULL; RageException::ThrowNonfatal("Unable to create audio channel"); } SndCommand cmd; cmd.cmd = clockComponentCmd; cmd.param1 = true; cmd.param2 = 0; err |= SndDoImmediate(channel, &cmd); cmd.cmd = getClockComponentCmd; cmd.param1 = 0; cmd.param2 = reinterpret_cast(&clock); err |= SndDoImmediate(channel, &cmd); last_pos = 0; cmd.cmd = callBackCmd; cmd.param2 = 0; err |= SndDoCommand(channel, &cmd, false); if (err != noErr) RageException::ThrowNonfatal("Unable to create audio channel");*/ } RageSound_QT::~RageSound_QT() { /*if (channel) SndDisposeChannel(channel, true); SAFE_DELETE_ARRAY(buffer[0]); SAFE_DELETE_ARRAY(buffer[1]); if (soundOutput) CloseComponent(soundOutput);*/ } void RageSound_QT::GetData(SndChannel *chan, SndCommand *cmd_passed) { /*while (!SOUNDMAN) SDL_Delay(10); LockMutex L(SOUNDMAN->lock); static bool gettingData=false; static int recursiveCalls = 0; if (gettingData) { LOG->Warn( "GetData() called recursively %D times.", ++recursiveCalls); if (recursiveCalls >=10) RageException::Throw("GetData() called recursively too many times."); } else recursiveCalls = 0; gettingData = true; static SoundMixBuffer mix; RageSound_QT *P = reinterpret_cast(chan->userInfo); fill_me = cmd_passed->param2; UInt32 play_me = !fill_me; if (!P->last_pos){ TimeRecord tr; ClockGetTime(P->clock, &tr); UInt64 temp = tr.value.hi; temp <<= 32; temp |= tr.value.lo; double d = static_cast(temp)/tr.scale*freq; temp = static_cast(d); P->last_pos = static_cast(temp % 0x00000000FFFFFFFFLL); } else P->last_pos += samples; /* Swap buffers * / header.samplePtr = reinterpret_cast(buffer[play_me]); SndCommand cmd; cmd.cmd = bufferCmd; cmd.param1 = 0; cmd.param2 = reinterpret_cast(&header); SndDoCommand(chan, &cmd, 0); /* Clear the fill buffer * / memset(buffer[fill_me], 0, buffersize); for (unsigned i=0; isounds.size(); ++i) { if (P->sounds[i]->stopping) continue; unsigned got = P->sounds[i]->snd->GetPCM(reinterpret_cast(buffer[fill_me]), buffersize, P->last_pos); mix.write(reinterpret_cast(buffer[fill_me]), got / 2); if (got < buffersize) { P->sounds[i]->stopping = true; P->sounds[i]->flush_pos = P->last_pos + (got * 8 / samplesize); } } mix.read(reinterpret_cast(buffer[fill_me])); cmd.cmd = callBackCmd; cmd.param2 = play_me; SndDoCommand(chan, &cmd, 0); gettingData=false;*/ } void RageSound_QT::StartMixing(RageSound *snd) { /*sound *s = new sound; s->snd = snd; LockMutex L(SOUNDMAN->lock); sounds.push_back(s); LOG->Trace("There are %D sounds playing", sounds.size());*/ } void RageSound_QT::StopMixing(RageSound *snd) { /*LockMutex L(SOUNDMAN->lock); /* Find the sound. * / unsigned i; for(i = 0; i < sounds.size(); ++i) if(sounds[i]->snd == snd) break; if(i == sounds.size()) { LOG->Trace("not stopping a sound because it's not playing"); return; } delete sounds[i]; sounds.erase(sounds.begin()+i, sounds.begin()+i+1); LOG->Trace("There are %D sounds playing", sounds.size());*/ } void RageSound_QT::Update(float delta) { #pragma unused (delta) /*LockMutex L(SOUNDMAN->lock); vectorsnds = sounds; for (unsigned i = 0; i < snds.size(); ++i) { if (!sounds[i]->stopping) continue; if (GetPosition(snds[i]->snd) < sounds[i]->flush_pos) continue; snds[i]->snd->StopPlaying(); }*/ } int RageSound_QT::GetPosition(const RageSound *snd) const { #pragma unused (snd) /*TimeRecord tr; ClockGetTime(clock, &tr); UInt64 temp = tr.value.hi; temp <<= 32; temp |= tr.value.lo; double d = static_cast(temp)/tr.scale*freq; temp = static_cast(d); return static_cast(temp % 0x00000000FFFFFFFFLL);*/ } float RageSound_QT::GetPlayLatency() const { //return latency; }