--- linuxsampler/trunk/src/engines/EngineBase.h 2012/03/10 16:16:14 2327 +++ linuxsampler/trunk/src/engines/EngineBase.h 2013/05/03 14:26:32 2448 @@ -4,7 +4,7 @@ * * * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck * * Copyright (C) 2005-2008 Christian Schoenebeck * - * Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev * + * Copyright (C) 2009-2013 Christian Schoenebeck and Grigor Iliev * * * * 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 * @@ -104,7 +104,7 @@ * @param Samples - number of sample points to be rendered * @returns 0 on success */ - virtual int RenderAudio(uint Samples) { + virtual int RenderAudio(uint Samples) OVERRIDE { dmsg(8,("RenderAudio(Samples=%d)\n", Samples)); // return if engine disabled @@ -143,6 +143,10 @@ } } } + + // In case scale tuning has been changed, recalculate pitch for + // all active voices. + ProcessScaleTuningChange(); // reset internal voice counter (just for statistic of active voices) ActiveVoiceCountTemp = 0; @@ -205,9 +209,9 @@ return 0; } - virtual int MaxVoices() { return pVoicePool->poolSize(); } + virtual int MaxVoices() OVERRIDE { return pVoicePool->poolSize(); } - virtual void SetMaxVoices(int iVoices) throw (Exception) { + virtual void SetMaxVoices(int iVoices) throw (Exception) OVERRIDE { if (iVoices < 1) throw Exception("Maximum voices for an engine cannot be set lower than 1"); @@ -250,11 +254,11 @@ /** Called after the new max number of voices is set and before resuming the engine. */ virtual void PostSetMaxVoices(int iVoices) { } - virtual uint DiskStreamCount() { return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0; } - virtual uint DiskStreamCountMax() { return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0; } - virtual int MaxDiskStreams() { return iMaxDiskStreams; } + virtual uint DiskStreamCount() OVERRIDE { return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0; } + virtual uint DiskStreamCountMax() OVERRIDE { return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0; } + virtual int MaxDiskStreams() OVERRIDE { return iMaxDiskStreams; } - virtual void SetMaxDiskStreams(int iStreams) throw (Exception) { + virtual void SetMaxDiskStreams(int iStreams) throw (Exception) OVERRIDE { if (iStreams < 0) throw Exception("Maximum disk streams for an engine cannot be set lower than 0"); @@ -269,9 +273,9 @@ ResumeAll(); } - virtual String DiskStreamBufferFillBytes() { return (pDiskThread) ? pDiskThread->GetBufferFillBytes() : ""; } - virtual String DiskStreamBufferFillPercentage() { return (pDiskThread) ? pDiskThread->GetBufferFillPercentage() : ""; } - virtual InstrumentManager* GetInstrumentManager() { return &instruments; } + virtual String DiskStreamBufferFillBytes() OVERRIDE { return (pDiskThread) ? pDiskThread->GetBufferFillBytes() : ""; } + virtual String DiskStreamBufferFillPercentage() OVERRIDE { return (pDiskThread) ? pDiskThread->GetBufferFillPercentage() : ""; } + virtual InstrumentManager* GetInstrumentManager() OVERRIDE { return &instruments; } /** * Connect this engine instance with the given audio output device. @@ -282,7 +286,7 @@ * * @param pAudioOut - audio output device to connect to */ - virtual void Connect(AudioOutputDevice* pAudioOut) { + virtual void Connect(AudioOutputDevice* pAudioOut) OVERRIDE { // caution: don't ignore if connecting to the same device here, // because otherwise SetMaxDiskStreams() implementation won't work anymore! @@ -368,6 +372,13 @@ pDedicatedVoiceChannelLeft = new AudioChannel(0, MaxSamplesPerCycle); pDedicatedVoiceChannelRight = new AudioChannel(1, MaxSamplesPerCycle); } + + // Implementattion for abstract method derived from Engine. + virtual void ReconnectAudioOutputDevice() OVERRIDE { + SuspendAll(); + if (pAudioOutputDevice) Connect(pAudioOutputDevice); + ResumeAll(); + } /** * Similar to @c Disable() but this method additionally kills all voices @@ -422,11 +433,12 @@ */ virtual void Suspend(RR* pRegion) { dmsg(2,("EngineBase: Suspending Region %x ...\n",pRegion)); - SuspendedRegionsMutex.Lock(); - SuspensionChangeOngoing.Set(true); - pPendingRegionSuspension = pRegion; - SuspensionChangeOngoing.WaitAndUnlockIf(true); - SuspendedRegionsMutex.Unlock(); + { + LockGuard lock(SuspendedRegionsMutex); + SuspensionChangeOngoing.Set(true); + pPendingRegionSuspension = pRegion; + SuspensionChangeOngoing.WaitAndUnlockIf(true); + } dmsg(2,("EngineBase: Region %x suspended.",pRegion)); } @@ -438,11 +450,12 @@ */ virtual void Resume(RR* pRegion) { dmsg(2,("EngineBase: Resuming Region %x ...\n",pRegion)); - SuspendedRegionsMutex.Lock(); - SuspensionChangeOngoing.Set(true); - pPendingRegionResumption = pRegion; - SuspensionChangeOngoing.WaitAndUnlockIf(true); - SuspendedRegionsMutex.Unlock(); + { + LockGuard lock(SuspendedRegionsMutex); + SuspensionChangeOngoing.Set(true); + pPendingRegionResumption = pRegion; + SuspensionChangeOngoing.WaitAndUnlockIf(true); + } dmsg(2,("EngineBase: Region %x resumed.\n",pRegion)); } @@ -565,12 +578,13 @@ public: int PendingStreamDeletions; RR* pPendingRegionSuspension; + SuspensionVoiceHandler(RR* pPendingRegionSuspension) { PendingStreamDeletions = 0; this->pPendingRegionSuspension = pPendingRegionSuspension; } - virtual bool Process(MidiKey* pMidiKey) { + virtual bool Process(MidiKey* pMidiKey) OVERRIDE { VoiceIterator itVoice = pMidiKey->pActiveVoices->first(); // if current key is not associated with this region, skip this key if (itVoice->GetRegion()->GetParent() != pPendingRegionSuspension) return false; @@ -578,7 +592,7 @@ return true; } - virtual void Process(VoiceIterator& itVoice) { + virtual void Process(VoiceIterator& itVoice) OVERRIDE { // request a notification from disk thread side for stream deletion const Stream::Handle hStream = itVoice->KillImmediately(true); if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream @@ -968,8 +982,6 @@ } case 10: { // panpot //TODO: not sample accurate yet - pChannel->GlobalPanLeft = PanCurve[128 - itControlChangeEvent->Param.CC.Value]; - pChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value]; pChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value; break; } @@ -1320,7 +1332,7 @@ * control and status variables. This method is protected by a mutex. */ virtual void ResetInternal() { - ResetInternalMutex.Lock(); + LockGuard lock(ResetInternalMutex); // make sure that the engine does not get any sysex messages // while it's reseting @@ -1349,7 +1361,6 @@ pEventQueue->init(); pSysexBuffer->init(); if (sysexDisabled) MidiInputPort::AddSysexListener(this); - ResetInternalMutex.Unlock(); } /** @@ -1445,6 +1456,22 @@ return -1; } + + /** + * Checks whether scale tuning setting has been changed since last + * time this method was called, if yes, it recalculates the pitch + * for all active voices. + */ + void ProcessScaleTuningChange() { + const bool changed = ScaleTuningChanged.readAndReset(); + if (!changed) return; + + for (int i = 0; i < engineChannels.size(); i++) { + EngineChannelBase* channel = + static_cast*>(engineChannels[i]); + channel->OnScaleTuningChanged(); + } + } private: Pool* pVoicePool; ///< Contains all voices that can be activated.