1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
|
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2015 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: SoundSDL2.hxx 3182 2015-07-10 18:59:03Z stephena $
//============================================================================
#ifndef SOUND_SDL2_HXX
#define SOUND_SDL2_HXX
namespace Emulation {
class OSystem;
#define SDL_MAIN_HANDLED
#include <SDL.h>
#include "bspf.h"
#include "TIASnd.h"
/**
This class implements the sound API for SDL.
@author Stephen Anthony and Bradford W. Mott
@version $Id: SoundSDL2.hxx 3182 2015-07-10 18:59:03Z stephena $
*/
class SoundSDL2
{
public:
/**
Create a new sound object. The init method must be invoked before
using the object.
*/
SoundSDL2(TIASound *tiasound);
/**
Destructor
*/
virtual ~SoundSDL2();
public:
/**
Enables/disables the sound subsystem.
@param state True or false, to enable or disable the sound system
*/
void setEnabled(bool);
/**
The system cycle counter is being adjusting by the specified amount. Any
members using the system cycle counter should be adjusted as needed.
@param amount The amount the cycle counter is being adjusted by
*/
void adjustCycleCounter(Int32 amount);
/**
Sets the number of channels (mono or stereo sound). Note that this
determines how the emulation should 'mix' the channels of the TIA sound
system (of which there are always two). It does not specify the actual
number of hardware channels that SDL should use; it will always attempt
to use two channels in hardware.
@param channels The number of channels
*/
void setChannels(uInt32 channels);
/**
Sets the display framerate. Sound generation for NTSC and PAL games
depends on the framerate, so we need to set it here.
@param framerate The base framerate depending on NTSC or PAL ROM
*/
void setFrameRate(float framerate);
/**
Initializes the sound device. This must be called before any
calls are made to derived methods.
*/
void open();
/**
Should be called to close the sound device. Once called the sound
device can be started again using the open method.
*/
void close();
/**
Set the mute state of the sound object. While muted no sound is played.
@param state Mutes sound if true, unmute if false
*/
void mute(bool state);
/**
Reset the sound device.
*/
void reset();
/**
Sets the sound register to a given value.
@param addr The register address
@param value The value to save into the register
@param cycle The system cycle at which the register is being updated
*/
void set(uInt16 addr, uInt8 value, Int32 cycle);
/**
Sets the volume of the sound device to the specified level. The
volume is given as a percentage from 0 to 100. Values outside
this range indicate that the volume shouldn't be changed at all.
@param percent The new volume percentage level for the sound device
*/
void setVolume(Int32 percent);
/**
Adjusts the volume of the sound device based on the given direction.
@param direction Increase or decrease the current volume by a predefined
amount based on the direction (1 = increase, -1 = decrease)
*/
void adjustVolume(Int8 direction);
public:
/**
Get a descriptor for this console class (used in error checking).
@return The name of the object
*/
string name() const { return "TIASound"; }
protected:
/**
Invoked by the sound callback to process the next sound fragment.
The stream is 16-bits (even though the callback is 8-bits), since
the TIASnd class always generates signed 16-bit stereo samples.
@param stream Pointer to the start of the fragment
@param length Length of the fragment
*/
void processFragment(Int16* stream, uInt32 length);
protected:
// Struct to hold information regarding a TIA sound register write
struct RegWrite
{
uInt16 addr;
uInt8 value;
double delta;
};
/**
A queue class used to hold TIA sound register writes before being
processed while creating a sound fragment.
*/
class RegWriteQueue
{
public:
/**
Create a new queue instance with the specified initial
capacity. If the queue ever reaches its capacity then it will
automatically increase its size.
*/
RegWriteQueue(uInt32 capacity = 512);
virtual ~RegWriteQueue();
public:
/**
Clear any items stored in the queue.
*/
void clear();
/**
Dequeue the first object in the queue.
*/
void dequeue();
/**
Return the duration of all the items in the queue.
*/
double duration() const;
/**
Enqueue the specified object.
*/
void enqueue(const RegWrite& info);
/**
Return the item at the front on the queue.
@return The item at the front of the queue.
*/
RegWrite& front() const;
/**
Answers the number of items currently in the queue.
@return The number of items in the queue.
*/
uInt32 size() const;
private:
// Increase the size of the queue
void grow();
private:
uInt32 myCapacity;
RegWrite *myBuffer;
uInt32 mySize;
uInt32 myHead;
uInt32 myTail;
private:
// Following constructors and assignment operators not supported
RegWriteQueue(const RegWriteQueue&) = delete;
RegWriteQueue(RegWriteQueue&&) = delete;
RegWriteQueue& operator=(const RegWriteQueue&) = delete;
RegWriteQueue& operator=(RegWriteQueue&&) = delete;
};
private:
// TIASound emulation object
TIASound *myTIASound;
// Indicates if the sound subsystem is to be initialized
bool myIsEnabled;
// Indicates if the sound device was successfully initialized
bool myIsInitializedFlag;
// Indicates the cycle when a sound register was last set
Int32 myLastRegisterSetCycle;
// Indicates the number of channels (mono or stereo)
uInt32 myNumChannels;
// Log base 2 of the selected fragment size
double myFragmentSizeLogBase2;
// The myFragmentSizeLogBase2 variable is used in only two places,
// both of which involve an expensive division in the sound
// processing callback
// These are pre-computed to speed up the callback as much as possible
double myFragmentSizeLogDiv1, myFragmentSizeLogDiv2;
// Indicates if the sound is currently muted
bool myIsMuted;
// Current volume as a percentage (0 - 100)
uInt32 myVolume;
// Audio specification structure
SDL_AudioSpec myHardwareSpec;
// Queue of TIA register writes
RegWriteQueue myRegWriteQueue;
private:
// Callback function invoked by the SDL Audio library when it needs data
static void callback(void* udata, uInt8* stream, int len);
// Following constructors and assignment operators not supported
SoundSDL2() = delete;
SoundSDL2(const SoundSDL2&) = delete;
SoundSDL2(SoundSDL2&&) = delete;
SoundSDL2& operator=(const SoundSDL2&) = delete;
SoundSDL2& operator=(SoundSDL2&&) = delete;
};
}
#endif
|