mirror of https://github.com/stella-emu/stella.git
299 lines
8.4 KiB
C++
299 lines
8.4 KiB
C++
//============================================================================
|
|
//
|
|
// 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-2017 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.
|
|
//============================================================================
|
|
|
|
#ifdef SOUND_SUPPORT
|
|
|
|
#ifndef SOUND_SDL2_HXX
|
|
#define SOUND_SDL2_HXX
|
|
|
|
class OSystem;
|
|
|
|
#include "SDL_lib.hxx"
|
|
|
|
#include "bspf.hxx"
|
|
#include "TIASnd.hxx"
|
|
#include "Sound.hxx"
|
|
|
|
/**
|
|
This class implements the sound API for SDL.
|
|
|
|
@author Stephen Anthony and Bradford W. Mott
|
|
*/
|
|
class SoundSDL2 : public Sound
|
|
{
|
|
public:
|
|
/**
|
|
Create a new sound object. The init method must be invoked before
|
|
using the object.
|
|
*/
|
|
SoundSDL2(OSystem& osystem);
|
|
|
|
/**
|
|
Destructor
|
|
*/
|
|
virtual ~SoundSDL2();
|
|
|
|
public:
|
|
/**
|
|
Enables/disables the sound subsystem.
|
|
|
|
@param state True or false, to enable or disable the sound system
|
|
*/
|
|
void setEnabled(bool state) override;
|
|
|
|
/**
|
|
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) override;
|
|
|
|
/**
|
|
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) override;
|
|
|
|
/**
|
|
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) override;
|
|
|
|
/**
|
|
Initializes the sound device. This must be called before any
|
|
calls are made to derived methods.
|
|
*/
|
|
void open() override;
|
|
|
|
/**
|
|
Should be called to close the sound device. Once called the sound
|
|
device can be started again using the open method.
|
|
*/
|
|
void close() override;
|
|
|
|
/**
|
|
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) override;
|
|
|
|
/**
|
|
Reset the sound device.
|
|
*/
|
|
void reset() override;
|
|
|
|
/**
|
|
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) override;
|
|
|
|
/**
|
|
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) override;
|
|
|
|
/**
|
|
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) override;
|
|
|
|
public:
|
|
/**
|
|
Saves the current state of this device to the given Serializer.
|
|
|
|
@param out The serializer device to save to.
|
|
@return The result of the save. True on success, false on failure.
|
|
*/
|
|
bool save(Serializer& out) const override;
|
|
|
|
/**
|
|
Loads the current state of this device from the given Serializer.
|
|
|
|
@param in The Serializer device to load from.
|
|
@return The result of the load. True on success, false on failure.
|
|
*/
|
|
bool load(Serializer& in) override;
|
|
|
|
/**
|
|
Get a descriptor for this console class (used in error checking).
|
|
|
|
@return The name of the object
|
|
*/
|
|
string name() const override { 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);
|
|
|
|
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:
|
|
unique_ptr<RegWrite[]> myBuffer;
|
|
uInt32 myCapacity;
|
|
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
|
|
|
|
#endif // SOUND_SUPPORT
|