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
|
#include "audio_sink.h"
#include "core/plugin.h"
#include "logger.h"
namespace audio
{
std::map<std::string, std::function<std::shared_ptr<AudioSink>()>> sink_registry;
AudioSink::AudioSink()
{
}
class DummyAudioSink : public AudioSink
{
public:
void set_samplerate(int) {}
void start() {}
void stop() {}
void push_samples(int16_t *, int) {}
public:
static std::string getID() { return "dummy"; }
static std::shared_ptr<AudioSink> getInstance() { return std::make_shared<DummyAudioSink>(); }
};
void registerSinks()
{
satdump::eventBus->fire_event<RegisterAudioSinkEvent>({sink_registry});
}
std::shared_ptr<AudioSink> get_default_sink()
{
if (sink_registry.count("portaudio"))
{
logger->info("Using PortAudio Sink");
return sink_registry["portaudio"]();
}
else if (sink_registry.count("rtaudio"))
{
logger->info("Using RTAudio Sink");
return sink_registry["rtaudio"]();
}
else
return std::make_shared<DummyAudioSink>();
}
bool has_sink()
{
return sink_registry.size() > 0;
}
// https://github.com/cpuimage/resampler, just wanted something super basic
int AudioSink::resample_s16(const int16_t *input, int16_t *output, int inSampleRate, int outSampleRate, int inputSize, int channels)
{
if (input == NULL)
return 0;
uint64_t outputSize = (uint64_t)(inputSize * (double)outSampleRate / (double)inSampleRate);
outputSize -= outputSize % channels;
if (output == NULL)
return outputSize;
double stepDist = ((double)inSampleRate / (double)outSampleRate);
const uint64_t fixedFraction = (1LL << 32);
const double normFixed = (1.0 / (1LL << 32));
uint64_t step = ((uint64_t)(stepDist * fixedFraction + 0.5));
uint64_t curOffset = 0;
for (uint32_t i = 0; i < outputSize; i += 1)
{
for (int c = 0; c < channels; c += 1)
{
*output++ = (int16_t)(input[c] + (input[c + channels] - input[c]) * ((double)(curOffset >> 32) + ((curOffset & (fixedFraction - 1)) * normFixed)));
}
curOffset += step;
input += (curOffset >> 32) * channels;
curOffset &= (fixedFraction - 1);
}
return outputSize;
}
}
|