123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- #include "main.h"
- #include "ExtendedRead.h"
- extern WM_MEDIA_TYPE *NewMediaType(IWMOutputMediaProps *props);
- ExtendedReadStruct::ExtendedReadStruct() : buffer(0), reader(0), streamNum(0), bufferUsed(0), endOfFile(false), length(0)
- {}
- ExtendedReadStruct::ExtendedReadStruct(IWMSyncReader *_reader) : buffer(0), reader(0), streamNum(0), bufferUsed(0), endOfFile(false), length(0)
- {
- reader = _reader;
- reader->AddRef();
- }
- #define CBCLASS ExtendedReadStruct
- START_DISPATCH;
- CB(IFC_AUDIOSTREAM_READAUDIO, ReadAudio)
- END_DISPATCH;
- ExtendedReadStruct::~ExtendedReadStruct()
- {
- if (reader)
- {
- reader->Close();
- reader->Release();
- }
- if (buffer)
- buffer->Release();
- }
- size_t ExtendedReadStruct::ReadAudio(void *_buffer, size_t len)
- {
- __int8 *dest = reinterpret_cast<__int8 *>(_buffer);
- int bytesCopied = 0;
- /*
- while we still have bytes left
- {
- read a buffer
- copy buffer to user passed buffer
- if we have stuff left in the buffer, save it and return
- if we hit EOF, return
- }
- */
- size_t frameSize = (BitSize()/8)*Channels();
- len -= (len % frameSize); // only do whole frames
- while (len)
- {
- if (buffer)
- {
- BYTE *bufferBytes;
- DWORD bufferTotal;
- buffer->GetBufferAndLength(&bufferBytes, &bufferTotal);
- if (bufferUsed < bufferTotal)
- {
- size_t toCopy = min(bufferTotal - bufferUsed, len);
- memcpy(dest, bufferBytes + bufferUsed, toCopy);
- bufferUsed += toCopy;
- len -= toCopy;
- dest += toCopy;
- bytesCopied += toCopy;
- if (bufferUsed == bufferTotal)
- {
- bufferUsed = 0;
- buffer->Release();
- buffer = 0;
- }
- }
- }
- else if (!endOfFile)
- {
- QWORD sampleTime, duration;
- DWORD flags;
- DWORD outputNum;
- WORD streamNum2;
- HRESULT hr;
- hr = reader->GetNextSample(streamNum, &buffer, &sampleTime, &duration, &flags, & outputNum, &streamNum2);
- if (hr == NS_E_NO_MORE_SAMPLES)
- endOfFile = true;
- }
- else
- return bytesCopied;
- }
- return bytesCopied;
- }
- bool ExtendedReadStruct::Open(const wchar_t *filename)
- {
- //mod.InitWM();
- if (!reader)
- {
- if (!SUCCEEDED(WMCreateSyncReader(NULL, 0, &reader)))
- {
- reader = 0;
- return false;
- }
- }
- if (SUCCEEDED(reader->Open(filename)))
- {
- return true;
- }
- else
- {
- reader->Release();
- reader = 0;
- return false;
- }
- }
- bool ExtendedReadStruct::FindOutput(int bits, int channels)
- {
- DWORD numOutputs, output, format, numFormats;
- IWMOutputMediaProps *formatProperties;
- GUID mediaType;
- DWORD audioOutputNum;
- if (FAILED((reader->GetOutputCount(&numOutputs))))
- return false;
- for (output = 0;output < numOutputs;output++)
- {
- HRESULT hr;
- DWORD speakerConfig;
- switch (channels)
- {
- case 1:
- speakerConfig = DSSPEAKER_MONO;
- break;
- case 2:
- speakerConfig = DSSPEAKER_STEREO;
- break;
- case 0:
- default:
- speakerConfig = config_audio_num_channels; // TODO: force max channels?
- }
- hr = reader->SetOutputSetting(output, g_wszSpeakerConfig, WMT_TYPE_DWORD, (BYTE *) & speakerConfig, sizeof(speakerConfig));
- assert(hr == S_OK);
- BOOL discreteChannels = TRUE;
- hr = reader->SetOutputSetting(output, g_wszEnableDiscreteOutput, WMT_TYPE_BOOL, (BYTE *) & discreteChannels , sizeof(discreteChannels));
- assert(hr == S_OK);
- if (FAILED(reader->GetOutputFormatCount(output, &numFormats)))
- continue;
- for (format = 0;format < numFormats;format++)
- {
- reader->GetOutputFormat(output, format, &formatProperties);
- formatProperties->GetType(&mediaType);
- if (mediaType != WMMEDIATYPE_Audio)
- continue;
- WM_MEDIA_TYPE *mediaType = NewMediaType(formatProperties);
- if (mediaType->subtype == WMMEDIASUBTYPE_PCM)
- {
- if (bits)
- {
- WAVEFORMATEXTENSIBLE *waveFormat = (WAVEFORMATEXTENSIBLE *) mediaType->pbFormat;
- if (waveFormat->Format.cbSize >= 22)
- waveFormat->Samples.wValidBitsPerSample = bits;
- waveFormat->Format.wBitsPerSample = bits;
- waveFormat->Format.nBlockAlign = (waveFormat->Format.wBitsPerSample / 8) * waveFormat->Format.nChannels;
- waveFormat->Format.nAvgBytesPerSec = waveFormat->Format.nSamplesPerSec * waveFormat->Format.nBlockAlign;
- if (FAILED(formatProperties->SetMediaType(mediaType)))
- {
- // blah, just use the default settings then
- delete[] mediaType;
- mediaType = NewMediaType(formatProperties);
- }
- }
- AudioFormat::Open(mediaType);
- delete[] mediaType;
- audioOutputNum = output;
- reader->SetOutputProps(audioOutputNum, formatProperties);
- reader->GetStreamNumberForOutput(audioOutputNum, &streamNum);
- formatProperties->Release();
- reader->SetReadStreamSamples(streamNum, FALSE);
- IWMHeaderInfo *headerInfo = 0;
- reader->QueryInterface(&headerInfo);
- WMT_ATTR_DATATYPE type = WMT_TYPE_QWORD;
- WORD byteLength = sizeof(QWORD);
- WORD blah = 0;
- headerInfo->GetAttributeByName(&blah, g_wszWMDuration, &type, (BYTE *)&length, &byteLength);
- headerInfo->Release();
- return true;
- }
- delete[] mediaType;
- formatProperties->Release();
- }
- }
- return false;
- }
- extern "C"
- __declspec(dllexport) intptr_t winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate)
- {
- ExtendedReadStruct *read = new ExtendedReadStruct;
- if (read->Open(fn)
- && read->FindOutput(*bps, *nch))
- {
- *nch = read->Channels();
- *bps = read->BitSize();
- *srate = read->SampleRate();
- __int64 bytespersec = ((*nch) * (*bps / 8) * (*srate));
- __int64 s = (bytespersec * ((__int64)read->length)) / (__int64)(1000 * 10000);
- *size = (int)s;
- return reinterpret_cast<intptr_t>(read);
- }
- else
- {
- delete read;
- return 0;
- }
- }
- extern "C"
- __declspec(dllexport) intptr_t winampGetExtendedRead_getData(intptr_t handle, char *dest, int len, int *killswitch)
- {
- ExtendedReadStruct *read = reinterpret_cast<ExtendedReadStruct *>(handle);
- return read->ReadAudio(dest, len);
- }
- extern "C"
- __declspec(dllexport) void winampGetExtendedRead_close(intptr_t handle)
- {
- ExtendedReadStruct *read = reinterpret_cast<ExtendedReadStruct *>(handle);
- delete read;
- }
|