diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/DecodeFile.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Winamp/DecodeFile.cpp')
-rw-r--r-- | Src/Winamp/DecodeFile.cpp | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/Src/Winamp/DecodeFile.cpp b/Src/Winamp/DecodeFile.cpp new file mode 100644 index 00000000..d1a07388 --- /dev/null +++ b/Src/Winamp/DecodeFile.cpp @@ -0,0 +1,202 @@ +/** (c) Nullsoft, Inc. C O N F I D E N T I A L + ** Filename: + ** Project: + ** Description: + ** Author: Ben Allison benski@nullsoft.com + ** Created: + **/ +#include "main.h" +#include <stddef.h> +#include "DecodeFile.h" +#include "ExtendedReader.h" +#include "OutputPluginAudioStream.h" +#include "ResamplingReader.h" +#include "CommonReader.h" + +// "input" means input FROM the decoder, "output" means output TO the person using the ifc_audiostream +static bool RequiresResampling(const AudioParameters *input, size_t outputChannels, size_t outputBits, size_t outputSampleRate) +{ + if (outputChannels != input->channels) + return true; // need to up or downmix + + if (outputBits != input->bitsPerSample) + return true; + + if (outputSampleRate != input->sampleRate) + return true; + + return false; +} + +static void SetResamplingParameters(const AudioParameters *input, size_t &outputChannels, size_t &outputBits, size_t &outputSampleRate) +{ + // channels + if (!outputChannels) + outputChannels=input->channels; + else if ((input->flags & AUDIOPARAMETERS_MAXCHANNELS) && input->channels <= outputChannels) + outputChannels = input->channels; + + // bits + if (!outputBits) outputBits = input->bitsPerSample; + + // samplerate + if (!outputSampleRate) + outputSampleRate = input->sampleRate; + else if ((input->flags & AUDIOPARAMETERS_MAXSAMPLERATE) && input->sampleRate <= outputSampleRate) + outputSampleRate = input->sampleRate; + +} + +ifc_audiostream *DecodeFile::OpenAudio(const wchar_t *filename, AudioParameters *parameters) +{ + // save some info + size_t outputChannels = parameters->channels; + size_t outputBits = parameters->bitsPerSample; + size_t outputSampleRate = parameters->sampleRate; + + CommonReader *reader = MakeReader(filename, parameters, true); + if (!reader) + return 0; + + // check if they've requested certain output parameters + if (outputChannels || outputBits || outputSampleRate) + { + SetResamplingParameters(parameters, outputChannels, outputBits, outputSampleRate); + + // check if we need any resampling/conversion + if (RequiresResampling(parameters, outputChannels, outputBits, outputSampleRate)) + { + Resampler *resampler = new Resampler(parameters->bitsPerSample, parameters->channels, parameters->sampleRate, + outputBits, outputChannels, outputSampleRate, parameters->flags & AUDIOPARAMETERS_FLOAT); + + if (!resampler->OK()) + { + parameters->errorCode = API_DECODEFILE_BAD_RESAMPLE; + delete resampler; + return 0; + } + + parameters->bitsPerSample = (uint32_t)outputBits; + parameters->channels = (uint32_t)outputChannels; + parameters->sampleRate = (uint32_t)outputSampleRate; + parameters->sizeBytes =(size_t)((double)parameters->sizeBytes * resampler->sizeFactor); + ResamplingReader *resampleReader = new ResamplingReader(resampler, reader, outputChannels * outputBits / 8); + + return resampleReader; + } + + } + return reader; +} + +ifc_audiostream *DecodeFile::OpenAudioBackground(const wchar_t *filename, AudioParameters *parameters) +{ + // save some info + size_t outputChannels = parameters->channels; + size_t outputBits = parameters->bitsPerSample; + size_t outputSampleRate = parameters->sampleRate; + + CommonReader *reader = MakeReader(filename, parameters, false); + if (!reader) + return 0; + + // check if they've requested certain output parameters + if (outputChannels || outputBits || outputSampleRate) + { + SetResamplingParameters(parameters, outputChannels, outputBits, outputSampleRate); + + // check if we need any resampling/conversion + if (RequiresResampling(parameters, outputChannels, outputBits, outputSampleRate)) + { + Resampler *resampler = new Resampler(parameters->bitsPerSample, parameters->channels, parameters->sampleRate, + outputBits, outputChannels, outputSampleRate, parameters->flags & AUDIOPARAMETERS_FLOAT); + + if (!resampler->OK()) + { + parameters->errorCode = API_DECODEFILE_BAD_RESAMPLE; + delete resampler; + delete reader; + return 0; + } + + parameters->bitsPerSample = (uint32_t)outputBits; + parameters->channels = (uint32_t)outputChannels; + parameters->sampleRate = (uint32_t)outputSampleRate; + + ResamplingReader *resampleReader = new ResamplingReader(resampler, reader, outputChannels * outputBits / 8); + + return resampleReader; + } + + } + return reader; +} + +CommonReader *DecodeFile::MakeReader(const wchar_t *filename, AudioParameters *parameters, bool useUnagi) +{ + In_Module *in; + int a = 0; + bool found = false; + + while (a >= 0) + { + OpenFunc open = 0, openFloat=0; + OpenWFunc openW=0, openWFloat=0; + GetDataFunc getData = 0; + CloseFunc close = 0; + SetTimeFunc setTime = 0; + + in = in_setmod_noplay(filename, &a); + if (!in) break; + if (a >= 0) a++; + + found = true; + + open = (OpenFunc)GetProcAddress(in->hDllInstance, "winampGetExtendedRead_open"); + openFloat = (OpenFunc)GetProcAddress(in->hDllInstance, "winampGetExtendedRead_open_float"); + openW = (OpenWFunc)GetProcAddress(in->hDllInstance, "winampGetExtendedRead_openW"); + openWFloat = (OpenWFunc)GetProcAddress(in->hDllInstance, "winampGetExtendedRead_openW_float"); + getData = (GetDataFunc)GetProcAddress(in->hDllInstance, "winampGetExtendedRead_getData"); + close = (CloseFunc)GetProcAddress(in->hDllInstance, "winampGetExtendedRead_close"); + setTime = (SetTimeFunc)GetProcAddress(in->hDllInstance, "winampGetExtendedRead_setTime"); //optional! + if ((open || openW) && getData && close) + { + ExtendedReader *reader = new ExtendedReader(open, openW, openFloat, openWFloat, getData, close, setTime); + if (reader->Open(filename, parameters)) + return reader; + else + delete reader; + } + + } + + if (!found || !useUnagi) + { + parameters->errorCode = API_DECODEFILE_UNSUPPORTED; + } + else + { + OutputPluginAudioStream *reader = new OutputPluginAudioStream; + in = in_setmod_noplay(filename, 0); + if (reader->Open(in, filename, parameters)) + return reader; + delete reader; + } + + return 0; +} + +void DecodeFile::CloseAudio(ifc_audiostream *audioStream) +{ + CommonReader *reader = static_cast<CommonReader *>(audioStream); + delete reader; + //audioStream=0; +} + + +#define CBCLASS DecodeFile +START_DISPATCH; +CB(API_DECODEFILE_OPENAUDIO, OpenAudio) +CB(API_DECODEFILE_OPENAUDIO2, OpenAudioBackground) +VCB(API_DECODEFILE_CLOSEAUDIO, CloseAudio) +END_DISPATCH; |