Skip to content

Commit

Permalink
Added classes and driver interface for sound
Browse files Browse the repository at this point in the history
  • Loading branch information
petschau committed Oct 11, 2023
1 parent b9300bd commit e7f67c2
Show file tree
Hide file tree
Showing 53 changed files with 7,315 additions and 7,624 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "catch/catch_amalgamated.hpp"
#include "Core.h"
#include "VirtualHost/Core.h"

using namespace CustomChipset;

Expand Down
11 changes: 0 additions & 11 deletions fellow/SRC/WinFellow.Core/Core.cpp

This file was deleted.

191 changes: 191 additions & 0 deletions fellow/SRC/WinFellow.Core/CustomChipset/Sound/Sound.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#pragma once

/*=========================================================================*/
/* Fellow */
/* */
/* Sound emulation */
/* */
/* Author: Petter Schau */
/* */
/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */
/* */
/* 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*=========================================================================*/

#include <cstdint>
#include "CustomChipset/Sound/SoundConfiguration.h"
#include "WavFileWriter.h"

using namespace CustomChipset;

constexpr uint32_t MAX_BUFFER_SAMPLES = 65536;

class Sound
{
private:
WavFileWriter _wavFileWriter;

sound_emulations _emulation;
sound_rates _rate;
bool _isStereo;
bool _is16Bits;
bool _wavCapture;
sound_filters _filter;
sound_notifications _notification;
int _volume;
bool _deviceFound;

/*===========================================================================*/
/* Buffer data */
/*===========================================================================*/

uint32_t _currentBuffer;
int16_t _left[2][MAX_BUFFER_SAMPLES], _right[2][MAX_BUFFER_SAMPLES]; /* Samplebuffer, 16-b.signed */
uint32_t _bufferLength; /* Current buffer length in ms */
uint32_t _bufferSampleCount; /* Current number of samples in the buffer */
uint32_t _bufferSampleCountMax; /* Maximum capacity of the buffer */

/*===========================================================================*/
/* Run-time data */
/*===========================================================================*/

uint32_t audiocounter; /* Used in 22050/44100 to decide samples */
uint32_t audioodd; /* Used for skipping samples in 22050 */
uint32_t _framecounter; /* Count frames, and then play */
uint32_t _scale;

double _filterValue45 = 0.857270436755215389; // 7000 Hz at 45454 Hz samplingrate
double _filterValue33 = 0.809385175167476725; // 7000 Hz at 33100 Hz samplingrate
double _filterValue22 = 0.727523105310746957; // 7000 Hz at 22005 Hz samplingrate
double _filterValue15 = 0.639362082983339100; // 7000 Hz at 15650 Hz samplingrate

double _amplitudeDiv45 = 7.035;
double _amplitudeDiv33 = 5.25;
double _amplitudeDiv22 = 3.67;
double _amplitudeDiv15 = 2.773;
double _lastRight = 0.0000000000;
double _lastLeft = 0.0000000000;

/*===========================================================================*/
/* Audio-registers */
/*===========================================================================*/

uint32_t _audpt[4]; /* Sample-DMA pointer */
uint32_t _audlen[4]; /* Length */
uint32_t _audper[4]; /* Used directly, NOTE: translated value */
uint32_t _audvol[4]; /* Volume, possibly not reloaded by state-machine */
uint32_t _auddat[4]; /* Last data word set by DMA or CPU */
bool _auddatSet[4]; /* Set TRUE whenever auddat is written */

/*===========================================================================*/
/* Internal variables used by state-machine */
/*===========================================================================*/

uint32_t _audlenw[4]; /* Length counter */
uint32_t _audpercounter[4]; /* Period counter */
uint32_t _auddatw[4]; /* Sample currently output, 16-bit signed */
uint32_t _audstate[4]; /* Current state for the channel */
uint32_t _audvolw[4]; /* Current volume, reloaded at some points */
uint32_t _audptw[4]; /* Current dma-pointer, reloaded at some points */

/*===========================================================================*/
/* Translation tables */
/*===========================================================================*/

uint32_t _periodTable[65536];
int16_t _volumes[256][64];
uint32_t _audioIrqMask[4] = {0x0080, 0x0100, 0x0200, 0x0400};
uint32_t _audioDmaconMask[4] = {0x1, 0x2, 0x4, 0x8};

uint32_t GetChannelNumber(uint32_t address);

void ExecuteState(uint32_t channel);
void State0(uint32_t channel);
void State1(uint32_t channel);
void State2(uint32_t channel);
void State3(uint32_t channel);
void State4(uint32_t channel);
void State5(uint32_t channel);
void State6(uint32_t channel);

void LowPass(uint32_t count, int16_t *bufferLeft, int16_t *bufferRight);
uint32_t ChannelUpdate(uint32_t channel, int16_t *bufferLeft, int16_t *bufferRight, uint32_t count, bool halfscale, bool odd);
void FrequencyHandler();

sound_rates GetRate();
uint32_t GetRateReal();
uint32_t GetBufferLength();
int GetVolume();

void SetBufferSampleCount(uint32_t sampleCount);
uint32_t GetBufferSampleCount();
void SetBufferSampleCountMax(uint32_t sampleCountMax);
uint32_t GetBufferSampleCountMax();
void SetDeviceFound(bool deviceFound);
bool GetDeviceFound();
void SetScale(uint32_t scale);
uint32_t GetScale();

void SetSampleVolume(uint8_t sampleIn, uint8_t volume, int16_t sampleOut);
int16_t GetSampleVolume(int8_t sampleIn, uint8_t volume);
void SetPeriodValue(uint32_t period, uint32_t value);
uint32_t GetPeriodValue(uint32_t period);

void VolumeTableInitialize(bool isStereo);
void PeriodTableInitialize(uint32_t outputRate);
void PlaybackInitialize();

void IOHandlersInstall();
void IORegistersClear();
void CopyBufferOverrunToCurrentBuffer(uint32_t availableSamples, uint32_t previousBuffer);

public:
void SetEmulation(sound_emulations emulation);
sound_emulations GetEmulation();
void SetIsStereo(bool isStereo);
bool GetIsStereo();
void SetIs16Bits(bool is16Bits);
bool GetIs16Bits();
void SetFilter(sound_filters filter);
sound_filters GetFilter();
void SetWAVDump(bool wavCapture);
bool GetWAVDump();
void SetNotification(sound_notifications notification);
sound_notifications GetNotification();
void SetRate(sound_rates rate);
void SetBufferLength(uint32_t ms);

void ChannelKill(uint32_t channel);
void ChannelEnable(uint32_t channel);

void SetAudXpth(uint16_t data, uint32_t address);
void SetAudXptl(uint16_t data, uint32_t address);
void SetAudXlen(uint16_t data, uint32_t address);
void SetAudXper(uint16_t data, uint32_t address);
void SetAudXvol(uint16_t data, uint32_t address);
void SetAudXdat(uint16_t data, uint32_t address);

void SetVolume(int volume);

void EndOfLine();
void HardReset();
void EmulationStart();
void EmulationStop();
void Startup();
void Shutdown();

Sound();
~Sound();
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

namespace CustomChipset
{
typedef enum { SOUND_15650, SOUND_22050, SOUND_31300, SOUND_44100 } sound_rates;
typedef enum { SOUND_NONE, SOUND_PLAY, SOUND_EMULATE } sound_emulations;
typedef enum { SOUND_FILTER_ORIGINAL, SOUND_FILTER_ALWAYS, SOUND_FILTER_NEVER } sound_filters;
typedef enum { SOUND_DSOUND_NOTIFICATION, SOUND_MMTIMER_NOTIFICATION } sound_notifications;
}
37 changes: 37 additions & 0 deletions fellow/SRC/WinFellow.Core/CustomChipset/Sound/WavFileWriter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include <cstdint>
#include <string>
#include "CustomChipset/Sound/SoundConfiguration.h"

class WavFileWriter
{
private:
FILE *_wavFile;
char _filename[256];
uint32_t _serial;
CustomChipset::sound_rates _rate;
uint32_t _rateReal;
bool _isStereo;
bool _is16Bits;
uint32_t _fileLength;
uint32_t _sampleCount;

void Mono8BitsAdd(int16_t *left, int16_t *right, uint32_t sampleCount);
void Stereo8BitsAdd(int16_t *left, int16_t *right, uint32_t sampleCount);
void Mono16BitsAdd(int16_t *left, int16_t *right, uint32_t sampleCount);
void Stereo16BitsAdd(int16_t *left, int16_t *right, uint32_t sampleCount);
void HeaderWrite();
void LengthUpdate();
void FileInit(CustomChipset::sound_rates rate, bool is16Bits, bool isStereo, uint32_t sampleRate);

public:
void Play(int16_t *left, int16_t *right, uint32_t sampleCount);
void EmulationStart(CustomChipset::sound_rates rate, bool is16Bits, bool isStereo, uint32_t sampleRate);
void EmulationStop();
void Startup();
void Shutdown();

WavFileWriter();
~WavFileWriter();
};
8 changes: 8 additions & 0 deletions fellow/SRC/WinFellow.Core/Driver/Drivers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once
#include "Driver/ISoundDriver.h"

class Drivers
{
public:
ISoundDriver* SoundDriver;
};
19 changes: 19 additions & 0 deletions fellow/SRC/WinFellow.Core/Driver/ISoundDriver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once
#include <cstdint>
#include "Driver/SoundDriverRuntimeConfiguration.h"

class ISoundDriver
{
public:
virtual void Play(int16_t *leftBuffer, int16_t *rightBuffer, uint32_t sampleCount) = 0;
virtual void PollBufferPosition() = 0;
virtual bool SetCurrentSoundDeviceVolume(int volume) = 0;

virtual bool EmulationStart(SoundDriverRuntimeConfiguration runtimeConfiguration) = 0;
virtual void EmulationStop() = 0;

virtual bool IsInitialized() = 0;

ISoundDriver() = default;
virtual ~ISoundDriver() = default;
};
17 changes: 17 additions & 0 deletions fellow/SRC/WinFellow.Core/Driver/SoundDriverRuntimeConfiguration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <cstdint>
#include "CustomChipset/Sound/SoundConfiguration.h"

struct SoundDriverRuntimeConfiguration
{
CustomChipset::sound_emulations PlaybackMode;
CustomChipset::sound_rates PlaybackRate;
CustomChipset::sound_filters FilterMode;
CustomChipset::sound_notifications NotificationMode;
bool IsStereo;
bool Is16Bits;
int Volume;
uint32_t ActualSampleRate;
uint32_t MaximumBufferSampleCount;
};
32 changes: 32 additions & 0 deletions fellow/SRC/WinFellow.Core/NullDriver/Sound/NullSound.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "NullSound.h"

void NullSound::Play(int16_t *leftBuffer, int16_t *rightBuffer, uint32_t sampleCount)
{
}

void NullSound::PollBufferPosition()
{
}

bool NullSound::SetCurrentSoundDeviceVolume(int volume)
{
return true;
}

void NullSound::HardReset()
{
}

bool NullSound::EmulationStart(SoundDriverRuntimeConfiguration runtimeConfiguration)
{
return true;
}

void NullSound::EmulationStop()
{
}

bool NullSound::IsInitialized()
{
return true;
}
19 changes: 19 additions & 0 deletions fellow/SRC/WinFellow.Core/NullDriver/Sound/NullSound.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include "Driver/ISoundDriver.h"

class NullSound : public ISoundDriver
{
public:
void Play(int16_t* leftBuffer, int16_t* rightBuffer, uint32_t sampleCount) override;
void PollBufferPosition() override;
bool SetCurrentSoundDeviceVolume(int volume) override;

void HardReset();
bool EmulationStart(SoundDriverRuntimeConfiguration runtimeConfiguration) override;
void EmulationStop() override;
bool IsInitialized() override;

NullSound() = default;
virtual ~NullSound() = default;
};
12 changes: 12 additions & 0 deletions fellow/SRC/WinFellow.Core/VirtualHost/Core.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "VirtualHost/Core.h"

// For the time being this has to be a singleton
Core _core = Core();

Core::Core() : Registers(), RegisterUtility(Registers), Drivers()
{
}

Core::~Core()
{
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "Driver/Drivers.h"
#include "CustomChipset/Sound/Sound.h"
#include "CustomChipset/Registers.h"
#include "CustomChipset/RegisterUtility.h"

Expand All @@ -8,7 +10,12 @@ class Core
public:
CustomChipset::Registers Registers;
CustomChipset::RegisterUtility RegisterUtility;
Drivers Drivers;

Sound *Sound;

Core();
~Core();
};

extern Core _core;
Loading

0 comments on commit e7f67c2

Please sign in to comment.