/** (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 #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(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;