Skip to content

Commit 635bbed

Browse files
committed
ADL: Add Sound class
1 parent f3e38cc commit 635bbed

File tree

6 files changed

+195
-115
lines changed

6 files changed

+195
-115
lines changed

engines/adl/adl.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,13 @@
3939
#include "adl/display.h"
4040
#include "adl/detection.h"
4141
#include "adl/graphics.h"
42-
#include "adl/speaker.h"
42+
#include "adl/sound.h"
4343

4444
namespace Adl {
4545

4646
AdlEngine::~AdlEngine() {
4747
delete _display;
4848
delete _graphics;
49-
delete _speaker;
5049
delete _console;
5150
delete _dumpFile;
5251
}
@@ -56,7 +55,6 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
5655
_dumpFile(nullptr),
5756
_display(nullptr),
5857
_graphics(nullptr),
59-
_speaker(nullptr),
6058
_isRestarting(false),
6159
_isRestoring(false),
6260
_isQuitting(false),
@@ -461,7 +459,25 @@ void AdlEngine::drawPic(byte pic, Common::Point pos) const {
461459
}
462460

463461
void AdlEngine::bell(uint count) const {
464-
_speaker->bell(count);
462+
Tones tones;
463+
464+
for (uint i = 0; i < count - 1; ++i) {
465+
tones.push_back(Tone(940.0, 100.0));
466+
tones.push_back(Tone(0.0, 12.0));
467+
}
468+
469+
tones.push_back(Tone(940.0, 100.0));
470+
471+
Audio::SoundHandle handle;
472+
Audio::AudioStream *stream = new Sound(tones);
473+
474+
g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &handle, stream);
475+
476+
while (!g_engine->shouldQuit() && g_system->getMixer()->isSoundHandleActive(handle)) {
477+
Common::Event event;
478+
pollEvent(event);
479+
g_system->delayMillis(16);
480+
}
465481
}
466482

467483
const Region &AdlEngine::getRegion(uint i) const {
@@ -644,7 +660,6 @@ Common::Error AdlEngine::run() {
644660
initGraphics(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, true);
645661

646662
_console = new Console(this);
647-
_speaker = new Speaker();
648663
_display = new Display();
649664

650665
setupOpcodeTables();

engines/adl/adl.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ namespace Adl {
5353
class Console;
5454
class Display;
5555
class GraphicsMan;
56-
class Speaker;
5756
struct AdlGameDescription;
5857
class ScriptEnv;
5958

@@ -347,7 +346,6 @@ friend class Console;
347346

348347
Display *_display;
349348
GraphicsMan *_graphics;
350-
Speaker *_speaker;
351349

352350
// Opcodes
353351
typedef Common::Functor1<ScriptEnv &, int> Opcode;

engines/adl/module.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ MODULE_OBJS := \
1919
hires4.o \
2020
hires5.o \
2121
hires6.o \
22-
speaker.o
22+
sound.o
2323

2424
MODULE_DIRS += \
2525
engines/adl

engines/adl/sound.cpp

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/* ScummVM - Graphic Adventure Engine
2+
*
3+
* ScummVM is the legal property of its developers, whose names
4+
* are too numerous to list here. Please refer to the COPYRIGHT
5+
* file distributed with this source distribution.
6+
*
7+
* This program is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU General Public License
9+
* as published by the Free Software Foundation; either version 2
10+
* of the License, or (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20+
*
21+
*/
22+
23+
#include "common/system.h"
24+
25+
#include "audio/mixer.h"
26+
27+
#include "adl/sound.h"
28+
29+
namespace Adl {
30+
31+
// Generic PC-speaker synth
32+
// This produces more accurate frequencies than Audio::PCSpeaker, but only
33+
// does square waves.
34+
class Speaker {
35+
public:
36+
Speaker(int sampleRate);
37+
38+
void startTone(double freq);
39+
void stopTone();
40+
void generateSamples(int16 *buffer, int numSamples);
41+
42+
private:
43+
int _rate;
44+
frac_t _halfWaveLen, _halfWaveRem;
45+
int16 _curSample;
46+
};
47+
48+
Speaker::Speaker(int sampleRate) :
49+
_rate(sampleRate),
50+
_curSample(32767) {
51+
52+
stopTone();
53+
}
54+
55+
void Speaker::startTone(double freq) {
56+
_halfWaveLen = _halfWaveRem = doubleToFrac(_rate / freq / 2);
57+
58+
if (_halfWaveLen < FRAC_ONE) {
59+
// Tone out of range at this sample rate
60+
stopTone();
61+
}
62+
}
63+
64+
void Speaker::stopTone() {
65+
_halfWaveLen = 0;
66+
_halfWaveRem = intToFrac(32767);
67+
}
68+
69+
void Speaker::generateSamples(int16 *buffer, int numSamples) {
70+
int offset = 0;
71+
72+
while (offset < numSamples) {
73+
if (_halfWaveRem >= 0 && _halfWaveRem < FRAC_ONE) {
74+
// Rising/falling edge
75+
// Switch level
76+
_curSample = ~_curSample;
77+
// Use transition point fraction for current sample value
78+
buffer[offset++] = _halfWaveRem ^ _curSample;
79+
// Compute next transition point
80+
_halfWaveRem += _halfWaveLen - FRAC_ONE;
81+
} else {
82+
// Low/high level (incl. silence)
83+
// Generate as many samples as we can
84+
const int samples = MIN(numSamples - offset, (int)fracToInt(_halfWaveRem));
85+
Common::fill(buffer + offset, buffer + offset + samples, _curSample);
86+
offset += samples;
87+
88+
// Count down to level transition point, unless we're playing silence
89+
if (_halfWaveLen > 0)
90+
_halfWaveRem -= intToFrac(samples);
91+
}
92+
}
93+
}
94+
95+
Sound::Sound(const Tones &tones) :
96+
_tones(tones),
97+
_toneIndex(0),
98+
_samplesRem(0) {
99+
100+
_rate = g_system->getMixer()->getOutputRate();
101+
_speaker = new Speaker(_rate);
102+
}
103+
104+
Sound::~Sound() {
105+
delete _speaker;
106+
}
107+
108+
bool Sound::endOfData() const {
109+
return _samplesRem == 0 && _toneIndex == _tones.size();
110+
}
111+
112+
int Sound::readBuffer(int16 *buffer, const int numSamples) {
113+
int offset = 0;
114+
115+
while (offset < numSamples) {
116+
if (_samplesRem == 0) {
117+
// Set up next tone
118+
119+
if (_toneIndex == _tones.size()) {
120+
// No more tones
121+
return offset;
122+
}
123+
124+
if (_tones[_toneIndex].freq == 0.0)
125+
_speaker->stopTone();
126+
else
127+
_speaker->startTone(_tones[_toneIndex].freq);
128+
129+
// Compute length of tone
130+
_samplesRem = _rate * _tones[_toneIndex++].len / 1000;
131+
}
132+
133+
// Generate as many samples as we can
134+
const int samples = MIN(numSamples - offset, _samplesRem);
135+
_speaker->generateSamples(buffer + offset, samples);
136+
137+
_samplesRem -= samples;
138+
offset += samples;
139+
}
140+
141+
return numSamples;
142+
}
143+
144+
} // End of namespace Adl

engines/adl/speaker.h renamed to engines/adl/sound.h

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,45 @@
2020
*
2121
*/
2222

23-
#ifndef ADL_SPEAKER_H
24-
#define ADL_SPEAKER_H
23+
#ifndef ADL_SOUND_H
24+
#define ADL_SOUND_H
2525

26-
#include "common/types.h"
26+
#include "audio/audiostream.h"
2727

28-
#include "audio/mixer.h"
29-
30-
namespace Audio {
31-
class AudioStream;
32-
}
28+
#include "common/array.h"
29+
#include "common/frac.h"
3330

3431
namespace Adl {
3532

36-
class Speaker {
33+
class Speaker;
34+
35+
struct Tone {
36+
double freq; // Hz
37+
double len; // ms
38+
39+
Tone(double frequency, double length) : freq(frequency), len(length) { }
40+
};
41+
42+
typedef Common::Array<Tone> Tones;
43+
44+
class Sound : public Audio::AudioStream {
3745
public:
38-
Speaker();
39-
~Speaker();
46+
Sound(const Tones &tones);
47+
~Sound();
4048

41-
void bell(uint count);
49+
// AudioStream
50+
int readBuffer(int16 *buffer, const int numSamples);
51+
bool isStereo() const { return false; }
52+
bool endOfData() const;
53+
int getRate() const { return _rate; }
4254

4355
private:
44-
byte *_bell, *_silence;
56+
const Tones &_tones;
57+
58+
Speaker *_speaker;
59+
int _rate;
60+
uint _toneIndex;
61+
int _samplesRem;
4562
};
4663

4764
} // End of namespace Adl

engines/adl/speaker.cpp

Lines changed: 0 additions & 94 deletions
This file was deleted.

0 commit comments

Comments
 (0)