bsnes/higan/audio/audio.cpp
Tim Allen 7cdae5195a Update to v098r07 release.
byuu says:

Changelog:
- GB: support modeSelect and RAM for MBC1M (Momotarou Collection)
- audio: implemented native resampling support into Emulator::Stream
- audio: removed nall::DSP completely

Unfortunately, the new resampler didn't turn out quite as fast as I had
hoped. The final hermite resampling added some overhead; and I had to
bump up the kernel count to 500 from 400 to get the buzzing to go away
on my main PC. I think that's due to it running at 48000hz output
instead of 44100hz output, maybe?

Compared to Ryphecha's:
(NES) Mega Man 2: 167fps -> 166fps
(GB) Mega Man II: 224fps -> 200fps
(WSC) Riviera: 143fps -> 151fps

Odd that the WS/WSC ends up faster while the DMG/CGB ends up slower.

But this knocks 922 lines down to 146 lines. The only files left in all
of higan not written (or rewritten) by me are ruby/xaudio2.h and
libco/ppc.c
2016-04-23 17:55:59 +10:00

88 lines
2.1 KiB
C++

#include <emulator/emulator.hpp>
namespace Emulator {
#include "stream.cpp"
Audio audio;
auto Audio::reset() -> void {
streams.reset();
setReverbDelay(reverbDelay);
}
auto Audio::setInterface(Interface* interface) -> void {
this->interface = interface;
}
auto Audio::setFrequency(double frequency) -> void {
this->frequency = frequency;
for(auto& stream : streams) stream->setFrequency(frequency);
}
auto Audio::setVolume(double volume) -> void {
this->volume = volume;
}
auto Audio::setBalance(double balance) -> void {
this->balance = balance;
}
auto Audio::setReverbDelay(uint reverbDelay) -> void {
this->reverbDelay = reverbDelay;
reverbLeft.resize(frequency * reverbDelay / 1000.0);
reverbRight.resize(frequency * reverbDelay / 1000.0);
memory::fill(reverbLeft.data(), reverbLeft.size() * sizeof(int16));
memory::fill(reverbRight.data(), reverbRight.size() * sizeof(int16));
}
auto Audio::setReverbLevel(double reverbLevel) -> void {
this->reverbLevel = reverbLevel;
}
auto Audio::createStream(uint channels, double frequency) -> shared_pointer<Stream> {
shared_pointer<Stream> stream = new Stream{channels, frequency};
stream->setFrequency(this->frequency);
streams.append(stream);
return stream;
}
//audio mixer
auto Audio::poll() -> void {
while(true) {
for(auto& stream : streams) {
if(!stream->pending()) return;
}
double left = 0.0, right = 0.0;
for(auto& stream : streams) {
double samples[2];
stream->read(samples);
left += samples[0];
right += samples[1];
}
left /= streams.size();
right /= streams.size();
if(balance < 0.0) right *= 1.0 + balance;
if(balance > 0.0) left *= 1.0 - balance;
//todo: apply volume, reverb before denormalization?
int ileft = (left * 65535.0) - 32768.0;
int iright = (right * 65535.0) - 32768.0;
ileft *= volume;
iright *= volume;
if(reverbDelay) {
reverbLeft.append(ileft);
reverbRight.append(iright);
ileft += reverbLeft.takeFirst() * reverbLevel;
iright += reverbRight.takeFirst() * reverbLevel;
}
interface->audioSample(sclamp<16>(ileft), sclamp<16>(iright));
}
}
}