From b1f6be7baa5c2d2c8c9441ea447db3145d9fc535 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sun, 18 Nov 2007 23:35:09 +0000 Subject: Moved Gob's square wave generator to sound/softsynth/pcspk.h svn-id: r29564 --- sound/softsynth/pcspk.cpp | 126 ++++++++++++++++++++++++++++++++++++++++++++++ sound/softsynth/pcspk.h | 86 +++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 sound/softsynth/pcspk.cpp create mode 100644 sound/softsynth/pcspk.h (limited to 'sound/softsynth') diff --git a/sound/softsynth/pcspk.cpp b/sound/softsynth/pcspk.cpp new file mode 100644 index 0000000000..444311c9a2 --- /dev/null +++ b/sound/softsynth/pcspk.cpp @@ -0,0 +1,126 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* 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 +* of the License, 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 this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* $URL$ +* $Id$ +* +*/ + +#include "sound/softsynth/pcspk.h" + +namespace Audio { + +const PCSpeaker::generatorFunc PCSpeaker::generateWave[] = + {&PCSpeaker::generateSquare, &PCSpeaker::generateSine, + &PCSpeaker::generateSaw, &PCSpeaker::generateTriangle}; + +PCSpeaker::PCSpeaker(int rate) { + _rate = rate; + _wave = kWaveFormSquare; + _playForever = false; + _oscLength = 0; + _oscSamples = 0; + _remainingSamples = 0; + _mixedSamples = 0; + _volume = 255; +} + +PCSpeaker::~PCSpeaker() { +} + +void PCSpeaker::play(WaveForm wave, int freq, int32 length) { + Common::StackLock lock(_mutex); + + assert((wave >= kWaveFormSquare) && (wave <= kWaveFormTriangle)); + + _wave = wave; + _oscLength = _rate / freq; + _oscSamples = 0; + if (length == -1) { + _remainingSamples = 1; + _playForever = true; + } else { + _remainingSamples = (_rate * length) / 1000; + _playForever = false; + } + _mixedSamples = 0; +} + +void PCSpeaker::stop(int32 delay) { + Common::StackLock lock(_mutex); + + _remainingSamples = (_rate * delay) / 1000; + _playForever = false; +} + +void PCSpeaker::setVolume(byte volume) { + _volume = volume; +} + +int PCSpeaker::readBuffer(int16 *buffer, const int numSamples) { + Common::StackLock lock(_mutex); + + int i; + + for (i = 0; _remainingSamples && (i < numSamples); i++) { + buffer[i] = generateWave[_wave](_oscSamples, _oscLength) * _volume; + if (_oscSamples++ >= _oscLength) + _oscSamples = 0; + if (!_playForever) + _remainingSamples--; + _mixedSamples++; + } + + // Clear the rest of the buffer + if (i < numSamples) + memset(buffer + i, 0, (numSamples - i) * sizeof(int16)); + + return numSamples; +} + +int8 PCSpeaker::generateSquare(uint32 x, uint32 oscLength) { + return (x < (oscLength / 2)) ? 127 : -128; +} + +int8 PCSpeaker::generateSine(uint32 x, uint32 oscLength) { + if (oscLength == 0) + return 0; + + // TODO: Maybe using a look-up-table would be better? + return CLIP((int16) (128 * sin(2.0 * M_PI * x / oscLength)), -128, 127); +} + +int8 PCSpeaker::generateSaw(uint32 x, uint32 oscLength) { + if (oscLength == 0) + return 0; + + return ((x * (65536 / oscLength)) >> 8) - 128; +} + +int8 PCSpeaker::generateTriangle(uint32 x, uint32 oscLength) { + if (oscLength == 0) + return 0; + + int y = ((x * (65536 / (oscLength / 2))) >> 8) - 128; + + return (x <= (oscLength / 2)) ? y : (256 - y); +} + +} // End of namespace Audio diff --git a/sound/softsynth/pcspk.h b/sound/softsynth/pcspk.h new file mode 100644 index 0000000000..17eb6320e5 --- /dev/null +++ b/sound/softsynth/pcspk.h @@ -0,0 +1,86 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 + * of the License, 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef SOUND_SOFTSYNTH_PCSPK_H +#define SOUND_SOFTSYNTH_PCSPK_H + +#include "sound/audiostream.h" +#include "sound/mixer.h" +#include "common/mutex.h" + +namespace Audio { + +class PCSpeaker : public AudioStream { +public: + enum WaveForm { + kWaveFormSquare = 0, + kWaveFormSine, + kWaveFormSaw, + kWaveFormTriangle + }; + + PCSpeaker(int rate = 44100); + ~PCSpeaker(); + + /** Play a note for length ms. + * + * If length is negative, play until told to stop. + */ + void play(WaveForm wave, int freq, int32 length); + /** Stop the currently playing note after delay ms. */ + void stop(int32 delay = 0); + /** Adjust the volume. */ + void setVolume(byte volume); + + int readBuffer(int16 *buffer, const int numSamples); + + bool isStereo() const { return false; } + bool endOfData() const { return false; } + bool endOfStream() const { return false; } + int getRate() const { return _rate; } + +protected: + Common::Mutex _mutex; + + int _rate; + WaveForm _wave; + bool _playForever; + uint32 _oscLength; + uint32 _oscSamples; + uint32 _remainingSamples; + uint32 _mixedSamples; + byte _volume; + + typedef int8 (*generatorFunc)(uint32, uint32); + static const generatorFunc generateWave[]; + + static int8 generateSquare(uint32 x, uint32 oscLength); + static int8 generateSine(uint32 x, uint32 oscLength); + static int8 generateSaw(uint32 x, uint32 oscLength); + static int8 generateTriangle(uint32 x, uint32 oscLength); +}; + +} // End of namespace Audio + +#endif // SOUND_SOFTSYNTH_PCSPEAKER_H -- cgit v1.2.3