aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/DecodeFile.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/DecodeFile.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Winamp/DecodeFile.cpp')
-rw-r--r--Src/Winamp/DecodeFile.cpp202
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;