mirror of
https://github.com/clangen/musikcube.git
synced 2024-11-19 20:13:36 +00:00
* Updated WasapiOut to provide the preferred sample rate for the
selected device * Updated FfmpegDecoder to accept the preferred sample rate from the output, and use it when resampling if it is non-negative. Otherwise, use the sample rate defined by the file. Note: this is not wired up in the main app yet.
This commit is contained in:
parent
f2e8fd45f8
commit
06bdf32959
@ -52,6 +52,8 @@ using namespace musik::core::sdk;
|
||||
static const char* TAG = "ffmpegdecoder";
|
||||
static IDebug* debug = nullptr;
|
||||
|
||||
#define RESOLVE_SAMPLE_RATE() this->preferredSampleRate > 0 ? this->preferredSampleRate : this->rate
|
||||
|
||||
extern "C" DLLEXPORT void SetDebug(IDebug* debug) {
|
||||
::debug = debug;
|
||||
}
|
||||
@ -149,6 +151,7 @@ FfmpegDecoder::FfmpegDecoder() {
|
||||
this->bufferSize = AV_INPUT_BUFFER_PADDING_SIZE + BUFFER_SIZE;
|
||||
this->buffer = new unsigned char[this->bufferSize];
|
||||
this->outputFifo = nullptr;
|
||||
this->preferredSampleRate = -1;
|
||||
}
|
||||
|
||||
FfmpegDecoder::~FfmpegDecoder() {
|
||||
@ -192,7 +195,7 @@ double FfmpegDecoder::SetPosition(double seconds) {
|
||||
|
||||
bool FfmpegDecoder::GetBuffer(IBuffer *buffer) {
|
||||
if (this->ioContext) {
|
||||
buffer->SetSampleRate((long) this->rate);
|
||||
buffer->SetSampleRate((long) RESOLVE_SAMPLE_RATE());
|
||||
buffer->SetChannels((long) this->channels);
|
||||
buffer->SetSamples(0);
|
||||
|
||||
@ -256,7 +259,7 @@ bool FfmpegDecoder::InitializeResampler(IBuffer* buffer) {
|
||||
this->resampler,
|
||||
this->codecContext->channel_layout,
|
||||
AV_SAMPLE_FMT_FLT,
|
||||
(int) this->rate,
|
||||
(int) RESOLVE_SAMPLE_RATE(),
|
||||
this->codecContext->channel_layout,
|
||||
this->codecContext->sample_fmt,
|
||||
this->codecContext->sample_rate,
|
||||
@ -404,7 +407,7 @@ bool FfmpegDecoder::ReadSendAndReceivePacket(AVPacket* packet) {
|
||||
this->resampledFrame = this->AllocFrame(
|
||||
this->resampledFrame,
|
||||
AV_SAMPLE_FMT_FLT,
|
||||
this->rate,
|
||||
RESOLVE_SAMPLE_RATE(),
|
||||
this->decodedFrame->nb_samples);
|
||||
|
||||
error = swr_convert_frame(
|
||||
|
@ -64,7 +64,7 @@ class FfmpegDecoder: public musik::core::sdk::IDecoder {
|
||||
double GetDuration() override;
|
||||
bool Open(musik::core::sdk::IDataStream *stream) override;
|
||||
bool Exhausted() override;
|
||||
void SetPreferredSampleRate(int rate) override { }
|
||||
void SetPreferredSampleRate(int rate) override { this->preferredSampleRate = rate; }
|
||||
|
||||
IDataStream* Stream() { return this->stream; }
|
||||
|
||||
@ -87,6 +87,7 @@ class FfmpegDecoder: public musik::core::sdk::IDecoder {
|
||||
AVFrame* resampledFrame;
|
||||
SwrContext* resampler;
|
||||
unsigned char* buffer;
|
||||
int preferredSampleRate { -1 };
|
||||
int bufferSize;
|
||||
int rate, channels;
|
||||
int streamId;
|
||||
|
@ -514,13 +514,27 @@ found_or_done:
|
||||
return result;
|
||||
}
|
||||
|
||||
bool WasapiOut::Configure(IBuffer *buffer) {
|
||||
HRESULT result;
|
||||
int WasapiOut::GetDefaultSampleRate() {
|
||||
int result = -1;
|
||||
this->InitializeAudioClient();
|
||||
if (this->audioClient) {
|
||||
WAVEFORMATEX* deviceFormat = nullptr;
|
||||
audioClient->GetMixFormat(&deviceFormat);
|
||||
if (deviceFormat) {
|
||||
result = deviceFormat->nSamplesPerSec;
|
||||
CoTaskMemFree(deviceFormat);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool WasapiOut::InitializeAudioClient() {
|
||||
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
|
||||
HRESULT result = S_FALSE;
|
||||
|
||||
if (!this->audioClient) {
|
||||
if (!this->enumerator) {
|
||||
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
|
||||
result = CoCreateInstance(
|
||||
__uuidof(MMDeviceEnumerator),
|
||||
NULL,
|
||||
@ -542,14 +556,7 @@ bool WasapiOut::Configure(IBuffer *buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
if (waveFormat.Format.nChannels == buffer->Channels() &&
|
||||
waveFormat.Format.nSamplesPerSec == buffer->SampleRate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
|
||||
if (!this->device) {
|
||||
bool preferredDeviceOk = false;
|
||||
|
||||
IMMDevice* preferredDevice = this->GetPreferredDevice();
|
||||
@ -573,6 +580,19 @@ bool WasapiOut::Configure(IBuffer *buffer) {
|
||||
if ((result = this->device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&this->audioClient)) != S_OK) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WasapiOut::Configure(IBuffer *buffer) {
|
||||
if (this->audioClient &&
|
||||
waveFormat.Format.nChannels == buffer->Channels() &&
|
||||
waveFormat.Format.nSamplesPerSec == buffer->SampleRate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
this->Reset();
|
||||
this->InitializeAudioClient();
|
||||
|
||||
DWORD speakerConfig = 0;
|
||||
switch (buffer->Channels()) {
|
||||
@ -605,6 +625,8 @@ bool WasapiOut::Configure(IBuffer *buffer) {
|
||||
wf.dwChannelMask = speakerConfig;
|
||||
wf.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||
|
||||
HRESULT result = S_FALSE;
|
||||
|
||||
DWORD streamFlags = 0;
|
||||
if (this->audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX *) &wf, 0) != S_OK) {
|
||||
streamFlags |= AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM;
|
||||
|
@ -70,6 +70,7 @@ class WasapiOut : public IOutput {
|
||||
IDeviceList* GetDeviceList() override;
|
||||
bool SetDefaultDevice(const char* deviceId) override;
|
||||
IDevice* GetDefaultDevice() override;
|
||||
int GetDefaultSampleRate() override;
|
||||
|
||||
void OnDeviceChanged() { this->deviceChanged = true; }
|
||||
|
||||
@ -81,6 +82,7 @@ class WasapiOut : public IOutput {
|
||||
};
|
||||
|
||||
bool Configure(IBuffer *buffer);
|
||||
bool InitializeAudioClient();
|
||||
void Reset();
|
||||
IMMDevice* GetPreferredDevice();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user