Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions

View File

@ -0,0 +1,70 @@
#include "api__mp3-mpg123.h"
#include "MP4Factory.h"
#include "mp3_in_mp4.h"
static const char serviceName[] = "MP4 MP3 Decoder";
static const char testString[] = "mp4a";
// {ADBFEC60-41B4-4903-980B-0FA7E33D3567}
static const GUID MPEG4_MP3_GUID =
{ 0xadbfec60, 0x41b4, 0x4903, { 0x98, 0xb, 0xf, 0xa7, 0xe3, 0x3d, 0x35, 0x67 } };
FOURCC MPEG4Factory::GetServiceType()
{
return WaSvc::MP4AUDIODECODER;
}
const char *MPEG4Factory::GetServiceName()
{
return serviceName;
}
GUID MPEG4Factory::GetGUID()
{
return MPEG4_MP3_GUID;
}
void *MPEG4Factory::GetInterface(int global_lock)
{
return new MPEG4_MP3;
}
int MPEG4Factory::SupportNonLockingInterface()
{
return 1;
}
int MPEG4Factory::ReleaseInterface(void *ifc)
{
//plugin.service->service_unlock(ifc);
MP4AudioDecoder *decoder = static_cast<MP4AudioDecoder *>(ifc);
MPEG4_MP3 *mp3Decoder = static_cast<MPEG4_MP3 *>(decoder);
delete mp3Decoder;
return 1;
}
const char *MPEG4Factory::GetTestString()
{
return testString;
}
int MPEG4Factory::ServiceNotify(int msg, int param1, int param2)
{
return 1;
}
#ifdef CBCLASS
#undef CBCLASS
#endif
#define CBCLASS MPEG4Factory
START_DISPATCH;
CB(WASERVICEFACTORY_GETSERVICETYPE, GetServiceType)
CB(WASERVICEFACTORY_GETSERVICENAME, GetServiceName)
CB(WASERVICEFACTORY_GETGUID, GetGUID)
CB(WASERVICEFACTORY_GETINTERFACE, GetInterface)
CB(WASERVICEFACTORY_SUPPORTNONLOCKINGGETINTERFACE, SupportNonLockingInterface)
CB(WASERVICEFACTORY_RELEASEINTERFACE, ReleaseInterface)
CB(WASERVICEFACTORY_GETTESTSTRING, GetTestString)
CB(WASERVICEFACTORY_SERVICENOTIFY, ServiceNotify)
END_DISPATCH;

View File

@ -0,0 +1,24 @@
#ifndef NULLSOFT_MP3_MP4FACTORY_H
#define NULLSOFT_MP3_MP4FACTORY_H
#include <api/service/waservicefactory.h>
#include <api/service/services.h>
class MPEG4Factory : public waServiceFactory
{
public:
FOURCC GetServiceType();
const char *GetServiceName();
GUID GetGUID();
void *GetInterface(int global_lock);
int SupportNonLockingInterface();
int ReleaseInterface(void *ifc);
const char *GetTestString();
int ServiceNotify(int msg, int param1, int param2);
protected:
RECVS_DISPATCH;
};
#endif

View File

@ -0,0 +1,26 @@
#include "NSVFactory.h"
#include "nsvmain.h"
#include "api__mp3-mpg123.h"
#include "../nsv/nsvlib.h"
IAudioDecoder *NSVFactory::CreateAudioDecoder(FOURCC format, IAudioOutput **output)
{
switch (format)
{
case NSV_MAKETYPE('M', 'P', '3', ' '):
{
MP3_Decoder *dec;
WASABI_API_MEMMGR->New(&dec);
return dec;
}
default:
return 0;
}
}
#define CBCLASS NSVFactory
START_DISPATCH;
CB(SVC_NSVFACTORY_CREATEAUDIODECODER, CreateAudioDecoder)
END_DISPATCH;
#undef CBCLASS

View File

@ -0,0 +1,19 @@
#pragma once
#include "../nsv/svc_nsvFactory.h"
// {66AFC6B1-BFFD-49e2-BA71-62009F5266B0}
static const GUID mp3_nsv_guid =
{ 0x66afc6b1, 0xbffd, 0x49e2, { 0xba, 0x71, 0x62, 0x0, 0x9f, 0x52, 0x66, 0xb0 } };
class NSVFactory : public svc_nsvFactory
{
public:
static const char *getServiceName() { return "MP3 NSV Decoder"; }
static GUID getServiceGuid() { return mp3_nsv_guid; }
IAudioDecoder *CreateAudioDecoder(FOURCC format, IAudioOutput **output) override;
protected:
RECVS_DISPATCH;
};

View File

@ -0,0 +1,279 @@
#include "ADTS_MPG123.h"
#include "../winamp/wa_ipc.h"
#include <math.h>
#include "../nsutil/pcm.h"
#include <assert.h>
ADTS_MPG123::ADTS_MPG123() : decoder(0), gain(1.f)
{
decoderDelay = 529;
bitsPerSample = 0;
allowRG = false;
useFloat = false;
channels = 0;
sampleRate = 0;
decode_buffer = 0;
decode_buffer_length = 0;
}
ADTS_MPG123::~ADTS_MPG123()
{
if (decoder) {
mpg123_delete(decoder);
decoder = 0;
}
free(decode_buffer);
}
int ADTS_MPG123::Initialize(bool forceMono, bool reverseStereo, bool allowSurround, int maxBits, bool _allowRG, bool _useFloat, bool _useCRC)
{
allowRG = _allowRG;
useFloat = _useFloat;
int downmix = 0;
if (reverseStereo)
downmix = 2;
else
downmix = forceMono ? 1 : 0;
bitsPerSample = maxBits;
decoder = mpg123_new(NULL, NULL);
long flags = MPG123_QUIET|MPG123_FORCE_FLOAT|MPG123_SKIP_ID3V2|MPG123_IGNORE_STREAMLENGTH|MPG123_IGNORE_INFOFRAME;
if (forceMono) {
flags |= MPG123_FORCE_MONO;
}
mpg123_param(decoder, MPG123_FLAGS, flags, 0);
mpg123_param(decoder, MPG123_RVA, MPG123_RVA_OFF, 0);
return 0;
}
bool ADTS_MPG123::Open(ifc_mpeg_stream_reader *file)
{
mpg123_open_feed(decoder);
if (allowRG) {
gain = file->MPEGStream_Gain();
}
return true;
}
void ADTS_MPG123::Close()
{
if (decoder) {
mpg123_delete(decoder);
decoder = 0;
}
}
bool ADTS_MPG123::_UpdateProperties()
{
if (decoder && (!channels || !sampleRate)) {
long sample_rate = 44100;
int channels = 2;
int encoding = 0;
if (mpg123_getformat(decoder, &sample_rate, &channels, &encoding) == MPG123_OK) {
this->channels = channels;
this->sampleRate = sample_rate;
}
}
return channels && sampleRate;
}
void ADTS_MPG123::GetOutputParameters(size_t *numBits, int *numChannels, int *sampleRate)
{
_UpdateProperties();
*sampleRate = this->sampleRate;
*numChannels = this->channels;
*numBits = bitsPerSample;
}
void ADTS_MPG123::CalculateFrameSize(int *frameSize)
{
_UpdateProperties();
*frameSize = (int)(bitsPerSample/8) * channels * mpg123_spf(decoder);
#if 0 // TODO?
if (decoder->GetStreamInfo()->GetLayer() == 1)
*frameSize *= 3;
#endif
}
void ADTS_MPG123::Flush(ifc_mpeg_stream_reader *file)
{
mpg123_open_feed(decoder);
}
size_t ADTS_MPG123::GetCurrentBitrate()
{
mpg123_frameinfo frameInfo;
if (mpg123_info(decoder, &frameInfo) == MPG123_OK) {
return frameInfo.bitrate;
} else {
return 0;
}
}
size_t ADTS_MPG123::GetDecoderDelay()
{
return decoderDelay;
}
static void Decimate(const float *input, void *output, size_t numSamples, size_t *outputWritten, int bitsPerSample, bool useFloat, float gain)
{
if (!useFloat)
{
// TODO seen a few crashes reported where 'output' is 0
nsutil_pcm_FloatToInt_Interleaved_Gain(output, input, bitsPerSample, numSamples, gain);
}
else if (gain != 1.f)
{
float *data = (float *)output;
for (size_t i=0;i<numSamples;i++)
data[i]*=gain;
//data[i]=input[i]*gain;
}
*outputWritten = numSamples * (bitsPerSample / 8);
}
int ADTS_MPG123::_Read(ifc_mpeg_stream_reader *_file)
{
int err;
do {
unsigned char buffer[4096];
size_t bytes = 0;
_file->MPEGStream_Read(buffer, sizeof(buffer), &bytes);
err = mpg123_feed(decoder, buffer, bytes);
} while (err == MPG123_NEED_MORE);
switch(err) {
case MPG123_OK:
return adts::SUCCESS;
case MPG123_NEED_MORE:
if (_file->MPEGStream_EOF()) {
return adts::ENDOFFILE;
} else {
return adts::NEEDMOREDATA;
}
default:
return adts::FAILURE;
}
}
/*
notes for mp3 surround implementations
need to check the first two frames for ancillary data
store first valid in temp
store second valid frame in delay line
decimate first valid into output buffer
ancillary data is stored one frame behind, so PCM data decoded from mp3 frame n combines with anc data from frame n+1
*/
int ADTS_MPG123::Sync(ifc_mpeg_stream_reader *_file, unsigned __int8 *output, size_t outputSize, size_t *outputWritten, size_t *bitrate)
{
if (outputWritten) {
*outputWritten = 0;
}
int err = _Read(_file);
if (err == adts::SUCCESS) {
err = mpg123_read(decoder, 0, 0, 0);
if (err == MPG123_NEED_MORE) {
return adts::NEEDMOREDATA;
}
if (err != MPG123_NEW_FORMAT
&& err != MPG123_OK) {
return adts::FAILURE;
}
_UpdateProperties();
mpg123_frameinfo frameInfo;
err = mpg123_info(decoder, &frameInfo);
if (err == MPG123_OK) {
*bitrate = frameInfo.bitrate;
return adts::SUCCESS;
} else {
return adts::NEEDMOREDATA;
}
} else {
return err;
}
}
int ADTS_MPG123::Decode(ifc_mpeg_stream_reader *_file, unsigned __int8 *output, size_t outputSize, size_t *outputWritten, size_t *bitrate, size_t *endCut)
{
bool retried=false;
for (;;) {
if (!decode_buffer) {
int channels = 2;
long sample_rate;
int encoding;
if (mpg123_getformat(decoder, &sample_rate, &channels, &encoding) == MPG123_OK) {
this->channels = channels;
decode_buffer_length = sizeof(float) * channels * mpg123_spf(decoder);
decode_buffer = (float *)malloc(decode_buffer_length);
if (!decode_buffer) {
return adts::FAILURE;
}
}
}
float *flData=useFloat?(float *)output:decode_buffer;
size_t flDataSize=useFloat?outputSize:decode_buffer_length;
size_t done=0;
int err = mpg123_read(decoder, (unsigned char *)flData, flDataSize, &done);
switch(err) {
case MPG123_OK:
{
Decimate(flData, output, done / sizeof(float), outputWritten, (int)bitsPerSample, useFloat, (float)gain);
mpg123_frameinfo frameInfo;
if (mpg123_info(decoder, &frameInfo) == MPG123_OK) {
*bitrate = frameInfo.bitrate;
}
}
return adts::SUCCESS;
case MPG123_NEW_FORMAT:
assert(done == 0);
return adts::SUCCESS;
case MPG123_NEED_MORE:
if (done) {
Decimate(flData, output, done / sizeof(float), outputWritten, (int)bitsPerSample, useFloat, (float)gain);
mpg123_frameinfo frameInfo;
if (mpg123_info(decoder, &frameInfo) == MPG123_OK) {
*bitrate = frameInfo.bitrate;
}
return adts::SUCCESS;
} else if (_file->MPEGStream_EOF()) {
return adts::ENDOFFILE;
} else {
if (retried) {
return adts::NEEDMOREDATA;
} else {
retried=true;
err = _Read(_file);
if (err != adts::SUCCESS) {
return err;
} else {
break;
}
}
}
default:
assert(done == 0);
return adts::FAILURE;
}
}
}
int ADTS_MPG123::GetLayer()
{
if (decoder) {
mpg123_frameinfo frameInfo;
mpg123_info(decoder, &frameInfo);
return frameInfo.layer;
} else {
return 0;
}
}
void ADTS_MPG123::Release()
{
delete this;
}

View File

@ -0,0 +1,50 @@
#ifndef NULLSOFT_IN_MP3_ADTS_MPG123_H
#define NULLSOFT_IN_MP3_ADTS_MPG123_H
#include "../Plugins/Input/in_mp3/adts.h"
#include "api__mp3-mpg123.h"
#include <mpg123.h>
// {4192FE3F-E843-445c-8D62-51BE5EE5E68C}
static const GUID adts_mpg123_guid =
{ 0x4192fe3f, 0xe843, 0x445c, { 0x8d, 0x62, 0x51, 0xbe, 0x5e, 0xe5, 0xe6, 0x8c } };
class ADTS_MPG123 : public adts
{
public:
static const char *getServiceName() { return "MPG123 stream Decoder"; }
static GUID getServiceGuid() { return adts_mpg123_guid; }
ADTS_MPG123();
~ADTS_MPG123();
int Initialize(bool forceMono, bool reverse_stereo, bool allowSurround, int maxBits, bool allowRG, bool _useFloat = false, bool _useCRC = false);
bool Open(ifc_mpeg_stream_reader *file);
void Close();
void GetOutputParameters(size_t *numBits, int *numChannels, int *sampleRate);
void CalculateFrameSize(int *frameSize);
void Flush(ifc_mpeg_stream_reader *file);
size_t GetCurrentBitrate();
size_t GetDecoderDelay();
int Sync(ifc_mpeg_stream_reader *file, unsigned __int8 *output, size_t outputSize, size_t *outputWritten, size_t *bitrate);
int Decode(ifc_mpeg_stream_reader *file, unsigned __int8 *output, size_t outputSize, size_t *outputWritten, size_t *bitrate, size_t *endCut);
int GetLayer();
void Release();
private:
mpg123_handle *decoder;
size_t bitsPerSample;
double gain;
bool allowRG;
bool useFloat;
int channels;
int sampleRate;
unsigned int decoderDelay;
int _Read(ifc_mpeg_stream_reader *file);
bool _UpdateProperties();
float *decode_buffer;
size_t decode_buffer_length;
};
#endif

View File

@ -0,0 +1,14 @@
#pragma once
#include <api/service/api_service.h>
extern api_service *serviceManager;
#define WASABI_API_SVC serviceManager
#include "../Agave/Config/api_config.h"
extern api_config *configApi;
#define AGAVE_API_CONFIG configApi
#include <api/memmgr/api_memmgr.h>
extern api_memmgr *memmgrApi;
#define WASABI_API_MEMMGR memmgrApi

View File

@ -0,0 +1,209 @@
#include "avi_mp3_decoder.h"
#include "../nsutil/pcm.h"
#include <assert.h>
int AVIDecoder::CreateAudioDecoder(const nsavi::AVIH *avi_header,
const nsavi::STRH *stream_header, const nsavi::STRF *stream_format, const nsavi::STRD *stream_data,
unsigned int preferred_bits, unsigned int max_channels, bool floating_point,
ifc_aviaudiodecoder **decoder)
{
nsavi::mp3_format *waveformat = (nsavi::mp3_format *)stream_format;
if (waveformat->format.format == nsavi::audio_format_mp3
||waveformat->format.format == nsavi::audio_format_mp2)
{
mpg123_handle *ctx = mpg123_new(NULL, NULL);
if (!ctx)
return CREATEDECODER_FAILURE;
long flags = MPG123_QUIET|MPG123_FORCE_FLOAT|MPG123_SKIP_ID3V2|MPG123_IGNORE_STREAMLENGTH|MPG123_IGNORE_INFOFRAME;
if (max_channels == 1) {
flags |= MPG123_FORCE_MONO;
}
mpg123_param(ctx, MPG123_FLAGS, flags, 0);
mpg123_param(ctx, MPG123_RVA, MPG123_RVA_OFF, 0);
*decoder = new AVIMP3Decoder(ctx, preferred_bits, max_channels, floating_point);
return CREATEDECODER_SUCCESS;
}
return CREATEDECODER_NOT_MINE;
}
#define CBCLASS AVIDecoder
START_DISPATCH;
CB(CREATE_AUDIO_DECODER, CreateAudioDecoder)
END_DISPATCH;
#undef CBCLASS
#define FHG_DELAY 529
AVIMP3Decoder::AVIMP3Decoder(mpg123_handle *mp3, unsigned int bps, unsigned max_channels, bool floating_point)
: mp3(mp3), bits(bps?bps:16), max_channels(max_channels?max_channels:2), floating_point(floating_point), channels(0)
{
mpg123_open_feed(mp3);
pregap = FHG_DELAY;
channels = 0;
decode_buffer=0;
decode_buffer_length=0;
}
AVIMP3Decoder::~AVIMP3Decoder()
{
if (mp3) {
mpg123_delete(mp3);
mp3 = 0;
}
free(decode_buffer);
}
int AVIMP3Decoder::OutputFrameSize(size_t *frame_size)
{
long sample_rate = 44100;
int channels = 2;
int encoding = 0;
if (mpg123_getformat(mp3, &sample_rate, &channels, &encoding) == MPG123_OK) {
this->channels = channels;
}
*frame_size = (bits/8) * channels * mpg123_spf(mp3);
#if 0 // TODO?
if (mp3->GetStreamInfo()->GetLayer() == 1)
*frame_size *= 3;
#endif
return AVI_SUCCESS;
}
int AVIMP3Decoder::GetOutputProperties(unsigned int *sampleRate, unsigned int *_channels, unsigned int *bitsPerSample, bool *isFloat)
{
long sample_rate = 44100;
int channels = 2;
int encoding = 0;
if (mpg123_getformat(mp3, &sample_rate, &channels, &encoding) == MPG123_OK) {
this->channels = channels;
*sampleRate = sample_rate;
*_channels = channels;
*bitsPerSample = bits;
*isFloat = floating_point;
return AVI_SUCCESS;
}
else
{
return AVI_FAILURE;
}
}
int AVIMP3Decoder::DecodeChunk(uint16_t type, void **inputBuffer, size_t *inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
{
if (!mp3)
return AVI_FAILURE;
if (inputBufferBytes) {
const uint8_t *mp3_buffer = (const uint8_t *)*inputBuffer;
int err = mpg123_feed(mp3, mp3_buffer, *inputBufferBytes);
if (err == MPG123_OK) {
mp3_buffer += *inputBufferBytes;
*inputBuffer = (void *)mp3_buffer;
*inputBufferBytes = 0;
}
}
size_t output_buffer_len = *outputBufferBytes;
*outputBufferBytes = 0;
for (;;) {
if (!decode_buffer) {
int channels = 2;
long sample_rate;
int encoding;
if (mpg123_getformat(mp3, &sample_rate, &channels, &encoding) == MPG123_OK) {
this->channels = channels;
decode_buffer_length = sizeof(float) * channels * mpg123_spf(mp3);
decode_buffer = (float *)malloc(decode_buffer_length);
if (!decode_buffer) {
return AVI_FAILURE;
}
}
}
// get the decoded data out
// TODO: if floating_point is true and pregap is 0, decode straight into outputBuffer
size_t pcm_buf_used=0;
int err = mpg123_read(mp3, (unsigned char *)decode_buffer, decode_buffer_length, &pcm_buf_used);
if (err == MPG123_NEED_MORE && pcm_buf_used == 0) {
if (*outputBufferBytes == 0) {
return AVI_NEED_MORE_INPUT;
} else {
return AVI_SUCCESS;
}
} else if (err == MPG123_NEW_FORMAT) {
assert(pcm_buf_used == 0);
continue;
} else if (err == MPG123_OK || pcm_buf_used) {
if (!channels) {
long sample_rate = 44100;
int channels = 2;
int encoding = 0;
if (mpg123_getformat(mp3, &sample_rate, &channels, &encoding) == MPG123_OK) {
this->channels = channels;
} else {
return AVI_FAILURE;
}
}
// deal with pregap
size_t numSamples = pcm_buf_used / sizeof(float);
size_t offset = min(numSamples, pregap * channels);
numSamples -= offset;
pregap -= (int)offset / channels;
float *pcm_buf = decode_buffer + offset;
if (numSamples * bits / 8 > output_buffer_len) {
return AVI_SUCCESS;
}
// convert to destination sample format
if (floating_point)
{
memcpy(outputBuffer, pcm_buf, numSamples*bits/8);
}
else
{
nsutil_pcm_FloatToInt_Interleaved_Gain(outputBuffer, pcm_buf, bits, numSamples, 1.0);
}
*outputBufferBytes = *outputBufferBytes + numSamples * bits / 8;
outputBuffer = (char *)outputBuffer + numSamples * bits / 8;
output_buffer_len -= numSamples * bits / 8;
//return AVI_SUCCESS;
} else {
assert(pcm_buf_used == 0);
return AVI_FAILURE;
}
}
return AVI_SUCCESS;
}
void AVIMP3Decoder::Flush()
{
mpg123_open_feed(mp3);
pregap = FHG_DELAY;
}
void AVIMP3Decoder::Close()
{
if (mp3) {
mpg123_delete(mp3);
mp3 = 0;
}
delete this;
}
#define CBCLASS AVIMP3Decoder
START_DISPATCH;
CB(OUTPUT_FRAME_SIZE, OutputFrameSize)
CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
CB(DECODE_CHUNK, DecodeChunk)
VCB(FLUSH, Flush)
VCB(CLOSE, Close)
END_DISPATCH;
#undef CBCLASS

View File

@ -0,0 +1,45 @@
#pragma once
#include "../Plugins/Input/in_avi/svc_avidecoder.h"
#include "../Plugins/Input/in_avi/ifc_aviaudiodecoder.h"
#include <mpg123.h>
// {11D89BF5-014E-463a-B284-385FF0662FCC}
static const GUID avi_mp3_guid =
{ 0x11d89bf5, 0x14e, 0x463a, { 0xb2, 0x84, 0x38, 0x5f, 0xf0, 0x66, 0x2f, 0xcc } };
class AVIDecoder : public svc_avidecoder
{
public:
static const char *getServiceName() { return "MP3 AVI Decoder"; }
static GUID getServiceGuid() { return avi_mp3_guid; }
int CreateAudioDecoder(const nsavi::AVIH *avi_header, const nsavi::STRH *stream_header, const nsavi::STRF *stream_format, const nsavi::STRD *stream_data, unsigned int preferred_bits, unsigned int max_channels, bool floating_point, ifc_aviaudiodecoder **decoder);
protected:
RECVS_DISPATCH;
};
class AVIMP3Decoder : public ifc_aviaudiodecoder
{
public:
AVIMP3Decoder(mpg123_handle *mp3, unsigned int bps, unsigned max_channels, bool floating_point);
~AVIMP3Decoder();
protected:
RECVS_DISPATCH;
private:
/* ifc_mkvaudiodecoder implementation */
int OutputFrameSize(size_t *frame_size);
int GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat);
int DecodeChunk(uint16_t type, void **inputBuffer, size_t *inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes);
void Flush();
void Close();
private:
mpg123_handle *mp3;
unsigned int bits;
int pregap;
unsigned int max_channels;
bool floating_point;
unsigned int channels;
float *decode_buffer;
size_t decode_buffer_length;
};

View File

@ -0,0 +1,194 @@
#include "flv_mp3_decoder.h"
#include "../nsutil/pcm.h"
int FLVDecoderCreator::CreateAudioDecoder(int stereo, int bits, int sample_rate, int format_type, ifc_flvaudiodecoder **decoder)
{
if (format_type == FLV::AUDIO_FORMAT_MP3 || format_type == FLV::AUDIO_FORMAT_MP3_8KHZ)
{
mpg123_handle *ctx = mpg123_new(NULL, NULL);
if (!ctx)
return CREATEDECODER_FAILURE;
long flags = MPG123_QUIET|MPG123_FORCE_FLOAT|MPG123_SKIP_ID3V2|MPG123_IGNORE_STREAMLENGTH|MPG123_IGNORE_INFOFRAME;
if (!stereo) {
flags |= MPG123_FORCE_MONO;
}
mpg123_param(ctx, MPG123_FLAGS, flags, 0);
mpg123_param(ctx, MPG123_RVA, MPG123_RVA_OFF, 0);
*decoder = new FLVMP3(ctx);
return CREATEDECODER_SUCCESS;
}
return CREATEDECODER_NOT_MINE;
}
int FLVDecoderCreator::HandlesAudio(int format_type)
{
if (format_type == FLV::AUDIO_FORMAT_MP3 || format_type == FLV::AUDIO_FORMAT_MP3_8KHZ)
{
return CREATEDECODER_SUCCESS;
}
return CREATEDECODER_NOT_MINE;
}
#define CBCLASS FLVDecoderCreator
START_DISPATCH;
CB(CREATE_AUDIO_DECODER, CreateAudioDecoder)
CB(HANDLES_AUDIO, HandlesAudio)
END_DISPATCH;
#undef CBCLASS
/* --- */
#define FHG_DELAY 529
FLVMP3::FLVMP3(mpg123_handle *mp3) : mp3(mp3)
{
mpg123_open_feed(mp3);
bits = 16;
pregap = FHG_DELAY;
max_channels = 2;
channels = 0;
decode_buffer = 0;
decode_buffer_length = 0;
}
FLVMP3::~FLVMP3()
{
if (mp3) {
mpg123_delete(mp3);
mp3 = 0;
}
free(decode_buffer);
}
int FLVMP3::GetOutputFormat(unsigned int *sample_rate, unsigned int *_channels, unsigned int *_bits)
{
mpg123_frameinfo frameInfo;
if (mpg123_info(mp3, &frameInfo) == MPG123_OK)
{
*sample_rate = frameInfo.rate;
channels = (frameInfo.mode == MPG123_M_MONO)?1:2;
*_channels = channels;
*_bits = bits;
return FLV_AUDIO_SUCCESS;
}
else
{
return FLV_AUDIO_FAILURE;
}
}
int FLVMP3::DecodeSample(const void *input_buffer, size_t input_buffer_bytes, void *samples, size_t *samples_size_bytes, double *bitrate)
{
if (!mp3)
return FLV_AUDIO_FAILURE;
mpg123_feed(mp3, (unsigned char *)input_buffer, input_buffer_bytes);
*samples_size_bytes = 0;
*bitrate = 0;
for (;;) {
if (!decode_buffer) {
int channels = 2;
long sample_rate;
int encoding;
if (mpg123_getformat(mp3, &sample_rate, &channels, &encoding) == MPG123_OK) {
this->channels = channels;
decode_buffer_length = sizeof(float) * channels * mpg123_spf(mp3);
decode_buffer = (float *)malloc(decode_buffer_length);
if (!decode_buffer) {
return FLV_AUDIO_FAILURE;
}
}
}
// get the decoded data out
size_t pcm_buf_used=0;
int err = mpg123_read(mp3, (unsigned char *)decode_buffer, decode_buffer_length, &pcm_buf_used);
if (pcm_buf_used) {
if (!channels) {
long sample_rate = 44100;
int channels = 2;
int encoding = 0;
if (mpg123_getformat(mp3, &sample_rate, &channels, &encoding) == MPG123_OK) {
this->channels = channels;
} else {
return FLV_AUDIO_FAILURE;
}
}
// deal with pregap
size_t numSamples = pcm_buf_used / sizeof(float);
size_t offset = min(numSamples, pregap * channels);
numSamples -= offset;
pregap -= (int)offset / channels;
float *pcm_buf = decode_buffer + offset;
// convert to destination sample format
nsutil_pcm_FloatToInt_Interleaved(samples, pcm_buf, bits, numSamples);
*samples_size_bytes += numSamples * bits / 8;
samples = (char *)samples + numSamples * bits / 8;
mpg123_frameinfo frameInfo;
if (mpg123_info(mp3, &frameInfo) == MPG123_OK) {
*bitrate = frameInfo.bitrate;
}
return FLV_AUDIO_SUCCESS;
} else if (err == MPG123_NEED_MORE) {
*samples_size_bytes = 0;
return FLV_AUDIO_NEEDS_MORE_INPUT;
} else if (err == MPG123_NEW_FORMAT) {
continue;
} else if (err == MPG123_OK) {
continue;
}
else
return FLV_AUDIO_FAILURE;
}
return FLV_AUDIO_SUCCESS;
}
void FLVMP3::Flush()
{
mpg123_open_feed(mp3);
pregap = FHG_DELAY;
}
void FLVMP3::Close()
{
if (mp3) {
mpg123_delete(mp3);
mp3 = 0;
}
delete this;
}
void FLVMP3::SetPreferences(unsigned int _max_channels, unsigned int preferred_bits)
{
if (preferred_bits)
bits = preferred_bits;
if (max_channels > _max_channels)
max_channels = _max_channels;
long flags = MPG123_QUIET|MPG123_FORCE_FLOAT|MPG123_SKIP_ID3V2|MPG123_IGNORE_STREAMLENGTH|MPG123_IGNORE_INFOFRAME;
if (max_channels == 1) {
flags |= MPG123_FORCE_MONO;
}
mpg123_param(mp3, MPG123_FLAGS, flags, 0);
mpg123_param(mp3, MPG123_RVA, MPG123_RVA_OFF, 0);
}
#define CBCLASS FLVMP3
START_DISPATCH;
CB(FLV_AUDIO_GETOUTPUTFORMAT, GetOutputFormat)
CB(FLV_AUDIO_DECODE, DecodeSample)
VCB(FLV_AUDIO_FLUSH, Flush)
VCB(FLV_AUDIO_CLOSE, Close)
VCB(FLV_AUDIO_SETPREFERENCES, SetPreferences)
END_DISPATCH;
#undef CBCLASS

View File

@ -0,0 +1,44 @@
#pragma once
#include "../Plugins/Input/in_flv/svc_flvdecoder.h"
#include "../Plugins/Input/in_flv/FLVAudioHeader.h"
#include "../Plugins/Input/in_flv/ifc_flvaudiodecoder.h"
#include <mpg123.h>
// {5CAED3F6-ED5F-4801-921E-9BF86A483016}
static const GUID flv_mp3_guid =
{ 0x5caed3f6, 0xed5f, 0x4801, { 0x92, 0x1e, 0x9b, 0xf8, 0x6a, 0x48, 0x30, 0x16 } };
class FLVDecoderCreator : public svc_flvdecoder
{
public:
static const char *getServiceName() { return "MP3 FLV Decoder"; }
static GUID getServiceGuid() { return flv_mp3_guid; }
int CreateAudioDecoder(int stereo, int bits, int sample_rate, int format, ifc_flvaudiodecoder **decoder);
int HandlesAudio(int format_type);
protected:
RECVS_DISPATCH;
};
class FLVMP3 : public ifc_flvaudiodecoder
{
public:
FLVMP3(mpg123_handle *mp3);
~FLVMP3();
int GetOutputFormat(unsigned int *sample_rate, unsigned int *channels, unsigned int *bits);
int DecodeSample(const void *input_buffer, size_t input_buffer_bytes, void *samples, size_t *samples_size_bytes, double *bitrate);
void Flush();
void Close();
void SetPreferences(unsigned int max_channels, unsigned int preferred_bits);
private:
mpg123_handle *mp3;
unsigned int bits;
int pregap;
unsigned int max_channels;
unsigned int channels;
float *decode_buffer;
size_t decode_buffer_length;
protected:
RECVS_DISPATCH;
};

89
Src/mp3-mpg123/main.cpp Normal file
View File

@ -0,0 +1,89 @@
#include "api__mp3-mpg123.h"
#include "../nu/Singleton.h"
#include "../nu/factoryt.h"
#include "avi_mp3_decoder.h"
#include "flv_mp3_decoder.h"
#include "mkv_mp3_decoder.h"
#include "mp3_in_mp4.h"
#include "adts_mpg123.h"
#include "MP4Factory.h"
#include "NSVFactory.h"
#include <bfc/platform/export.h>
#include "../Agave/Component/ifc_wa5component.h"
#include "../nu/ServiceBuilder.h"
#include <mpg123.h>
api_service *WASABI_API_SVC = 0;
api_config *AGAVE_API_CONFIG = 0;
api_memmgr *WASABI_API_MEMMGR = 0;
class MP3DecoderComponent : public ifc_wa5component
{
public:
void RegisterServices(api_service *service);
int RegisterServicesSafeModeOk();
void DeregisterServices(api_service *service);
protected:
RECVS_DISPATCH;
};
static SingletonServiceFactory<svc_avidecoder, AVIDecoder> avi_factory;
static AVIDecoder avi_decoder;
static SingletonServiceFactory<svc_mkvdecoder, MKVDecoder> mkv_factory;
static MKVDecoder mkv_decoder;
static SingletonServiceFactory<svc_flvdecoder, FLVDecoderCreator> flv_factory;
static FLVDecoderCreator flv_decoder;
static MPEG4Factory mp4_factory;
static ServiceFactoryT<adts, ADTS_MPG123> adts_factory;
static NSVFactory nsv_decoder;
static SingletonServiceFactory<svc_nsvFactory, NSVFactory> nsv_factory;
void MP3DecoderComponent::RegisterServices(api_service *service)
{
WASABI_API_SVC = service;
if (mpg123_init() == MPG123_OK) {
WASABI_API_SVC->service_register(&mp4_factory);
avi_factory.Register(WASABI_API_SVC, &avi_decoder);
mkv_factory.Register(WASABI_API_SVC, &mkv_decoder);
flv_factory.Register(WASABI_API_SVC, &flv_decoder);
nsv_factory.Register(WASABI_API_SVC, &nsv_decoder);
adts_factory.Register(WASABI_API_SVC);
}
ServiceBuild(WASABI_API_SVC, AGAVE_API_CONFIG, AgaveConfigGUID);
ServiceBuild(WASABI_API_SVC, WASABI_API_MEMMGR, memMgrApiServiceGuid);
}
void MP3DecoderComponent::DeregisterServices(api_service *service)
{
avi_factory.Deregister(WASABI_API_SVC);
mkv_factory.Deregister(WASABI_API_SVC);
WASABI_API_SVC->service_deregister(&mp4_factory);
flv_factory.Deregister(WASABI_API_SVC);
nsv_factory.Deregister(WASABI_API_SVC);
adts_factory.Deregister(WASABI_API_SVC);
ServiceRelease(WASABI_API_SVC, AGAVE_API_CONFIG, AgaveConfigGUID);
ServiceRelease(WASABI_API_SVC, WASABI_API_MEMMGR, memMgrApiServiceGuid);
mpg123_exit();
}
int MP3DecoderComponent::RegisterServicesSafeModeOk()
{
return 1;
}
MP3DecoderComponent mp3_decoder_component;
extern "C" DLLEXPORT ifc_wa5component *GetWinamp5SystemComponent()
{
return &mp3_decoder_component;
}
#define CBCLASS MP3DecoderComponent
START_DISPATCH;
VCB(API_WA5COMPONENT_REGISTERSERVICES, RegisterServices)
CB(15, RegisterServicesSafeModeOk)
VCB(API_WA5COMPONENT_DEREEGISTERSERVICES, DeregisterServices)
END_DISPATCH;
#undef CBCLASS

View File

@ -0,0 +1,169 @@
#include "mkv_mp3_decoder.h"
#include "../nsutil/pcm.h"
int MKVDecoder::CreateAudioDecoder(const char *codec_id, const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data, unsigned int preferred_bits, unsigned int max_channels,bool floating_point, ifc_mkvaudiodecoder **decoder)
{
if (!strcmp(codec_id, "A_MPEG/L3")
|| !strcmp(codec_id, "A_MPEG/L2")
|| !strcmp(codec_id, "A_MPEG/L1"))
{
mpg123_handle *ctx = mpg123_new(NULL, NULL);
if (!ctx)
return CREATEDECODER_FAILURE;
long flags = MPG123_QUIET|MPG123_FORCE_FLOAT|MPG123_SKIP_ID3V2|MPG123_IGNORE_STREAMLENGTH|MPG123_IGNORE_INFOFRAME;
if (max_channels == 1) {
flags |= MPG123_FORCE_MONO;
}
mpg123_param(ctx, MPG123_FLAGS, flags, 0);
mpg123_param(ctx, MPG123_RVA, MPG123_RVA_OFF, 0);
*decoder = new MKVMP3Decoder(ctx, preferred_bits, max_channels, floating_point);
return CREATEDECODER_SUCCESS;
}
return CREATEDECODER_NOT_MINE;
}
#define CBCLASS MKVDecoder
START_DISPATCH;
CB(CREATE_AUDIO_DECODER, CreateAudioDecoder)
END_DISPATCH;
#undef CBCLASS
#define FHG_DELAY 529
MKVMP3Decoder::MKVMP3Decoder(mpg123_handle *mp3, unsigned int bps, unsigned max_channels, bool floating_point)
: mp3(mp3), bits(bps?bps:16), max_channels(max_channels?max_channels:2), floating_point(floating_point)
{
decode_buffer=0;
decode_buffer_length=0;
sample_rate = 0;
channels = 0;
pregap = FHG_DELAY;
mpg123_open_feed(mp3);
}
MKVMP3Decoder::~MKVMP3Decoder()
{
if (mp3) {
mpg123_delete(mp3);
mp3 = 0;
}
free(decode_buffer);
}
bool MKVMP3Decoder::_UpdateProperties()
{
if (mp3 && (!channels || !sample_rate)) {
long sample_rate = 44100;
int channels = 2;
int encoding = 0;
if (mpg123_getformat(mp3, &sample_rate, &channels, &encoding) == MPG123_OK) {
this->channels = channels;
this->sample_rate = sample_rate;
}
}
return channels && sample_rate;
}
int MKVMP3Decoder::OutputFrameSize(size_t *frame_size)
{
if (_UpdateProperties()) {
*frame_size = (bits/8) * channels * mpg123_spf(mp3);
return MKV_SUCCESS;
} else {
return MKV_FAILURE;
}
}
int MKVMP3Decoder::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat)
{
if (_UpdateProperties()) {
*sampleRate = this->sample_rate;
*channels = this->channels;
*bitsPerSample = bits;
*isFloat = floating_point;
return MKV_SUCCESS;
}
else
{
return MKV_FAILURE;
}
}
int MKVMP3Decoder::DecodeBlock(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
{
if (!mp3)
return MKV_FAILURE;
*outputBufferBytes = 0;
mpg123_feed(mp3, (unsigned char *)inputBuffer, inputBufferBytes);
for (;;) {
if (!decode_buffer) {
if (_UpdateProperties()) {
decode_buffer_length = sizeof(float) * channels * mpg123_spf(mp3);
decode_buffer = (float *)malloc(decode_buffer_length);
if (!decode_buffer) {
return MKV_FAILURE;
}
}
}
// get the decoded data out
size_t pcm_buf_used=0;
int err = mpg123_read(mp3, (unsigned char *)decode_buffer, decode_buffer_length, &pcm_buf_used);
if (pcm_buf_used) {
if (!_UpdateProperties()) {
return MKV_FAILURE;
}
// deal with pregap
size_t numSamples = pcm_buf_used / sizeof(float);
size_t offset = min(numSamples, pregap * channels);
numSamples -= offset;
pregap -= (int)offset / channels;
float *pcm_buf = decode_buffer + offset;
// convert to destination sample format
nsutil_pcm_FloatToInt_Interleaved(outputBuffer, pcm_buf, bits, numSamples);
*outputBufferBytes += numSamples * bits / 8;
outputBuffer = (char *)outputBuffer + numSamples * bits / 8;
return MKV_SUCCESS;
} else if (err == MPG123_NEED_MORE) {
*outputBufferBytes = 0;
return MKV_NEED_MORE_INPUT;
} else if (err == MPG123_NEW_FORMAT) {
continue;
} else if (err == MPG123_OK) {
continue;
}
else
return MKV_FAILURE;
}
return MKV_SUCCESS;
}
void MKVMP3Decoder::Flush()
{
mpg123_open_feed(mp3);
pregap = FHG_DELAY;
}
void MKVMP3Decoder::Close()
{
delete this;
}
#define CBCLASS MKVMP3Decoder
START_DISPATCH;
CB(OUTPUT_FRAME_SIZE, OutputFrameSize)
CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
CB(DECODE_BLOCK, DecodeBlock)
VCB(FLUSH, Flush)
VCB(CLOSE, Close)
END_DISPATCH;
#undef CBCLASS

View File

@ -0,0 +1,49 @@
#pragma once
#include "../Plugins/Input/in_mkv/svc_mkvdecoder.h"
#include "../Plugins/Input/in_mkv/ifc_mkvaudiodecoder.h"
#include <mpg123.h>
// {A08A5A0C-DEF7-4604-9F35-D5A5E9B1F4DF}
static const GUID mkv_mp3_guid =
{ 0xa08a5a0c, 0xdef7, 0x4604, { 0x9f, 0x35, 0xd5, 0xa5, 0xe9, 0xb1, 0xf4, 0xdf } };
class MKVDecoder : public svc_mkvdecoder
{
public:
static const char *getServiceName() { return "MP3 MKV Decoder"; }
static GUID getServiceGuid() { return mkv_mp3_guid; }
int CreateAudioDecoder(const char *codec_id, const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data, unsigned int preferred_bits, unsigned int preferred_channels, bool floating_point, ifc_mkvaudiodecoder **decoder);
protected:
RECVS_DISPATCH;
};
class MKVMP3Decoder : public ifc_mkvaudiodecoder
{
public:
MKVMP3Decoder(mpg123_handle *mp3, unsigned int bps, unsigned max_channels, bool floating_point);
~MKVMP3Decoder();
protected:
RECVS_DISPATCH;
private:
/* ifc_mkvaudiodecoder implementation */
int OutputFrameSize(size_t *frame_size);
int GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat);
int DecodeBlock(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes);
void Flush();
void Close();
private:
mpg123_handle *mp3;
unsigned int bits;
int pregap;
unsigned int max_channels;
unsigned int channels;
unsigned int sample_rate;
bool floating_point;
bool _UpdateProperties();
float *decode_buffer;
size_t decode_buffer_length;
};

View File

@ -0,0 +1,76 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (U.K.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.K.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -0,0 +1,44 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29609.76
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mp3-mpg123", "mp3-mpg123.vcxproj", "{5057C6D0-F787-43EB-BA3F-8D59AB3B09D1}"
ProjectSection(ProjectDependencies) = postProject
{DABE6307-F8DD-416D-9DAC-673E2DECB73F} = {DABE6307-F8DD-416D-9DAC-673E2DECB73F}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nsutil", "..\nsutil\nsutil.vcxproj", "{DABE6307-F8DD-416D-9DAC-673E2DECB73F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5057C6D0-F787-43EB-BA3F-8D59AB3B09D1}.Debug|Win32.ActiveCfg = Debug|Win32
{5057C6D0-F787-43EB-BA3F-8D59AB3B09D1}.Debug|Win32.Build.0 = Debug|Win32
{5057C6D0-F787-43EB-BA3F-8D59AB3B09D1}.Debug|x64.ActiveCfg = Debug|Win32
{5057C6D0-F787-43EB-BA3F-8D59AB3B09D1}.Debug|x64.Build.0 = Debug|Win32
{5057C6D0-F787-43EB-BA3F-8D59AB3B09D1}.Release|Win32.ActiveCfg = Release|Win32
{5057C6D0-F787-43EB-BA3F-8D59AB3B09D1}.Release|Win32.Build.0 = Release|Win32
{5057C6D0-F787-43EB-BA3F-8D59AB3B09D1}.Release|x64.ActiveCfg = Release|x64
{5057C6D0-F787-43EB-BA3F-8D59AB3B09D1}.Release|x64.Build.0 = Release|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|Win32.ActiveCfg = Debug|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|Win32.Build.0 = Debug|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|x64.ActiveCfg = Debug|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|x64.Build.0 = Debug|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|Win32.ActiveCfg = Release|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|Win32.Build.0 = Release|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|x64.ActiveCfg = Release|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FC646532-2050-40A5-A2AB-F699F1C071C4}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,285 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{5057C6D0-F787-43EB-BA3F-8D59AB3B09D1}</ProjectGuid>
<RootNamespace>mp3</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<TargetName>mp3</TargetName>
<TargetExt>.w5s</TargetExt>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<TargetName>mp3</TargetName>
<TargetExt>.w5s</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<TargetName>mp3</TargetName>
<TargetExt>.w5s</TargetExt>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<TargetName>mp3</TargetName>
<TargetExt>.w5s</TargetExt>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;UNICODE_INPUT_PLUGIN;DO_LAYER12;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
</Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;UNICODE_INPUT_PLUGIN;DO_LAYER12;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
</Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<IntrinsicFunctions>true</IntrinsicFunctions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;_USRDLL;UNICODE_INPUT_PLUGIN;DO_LAYER12;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ImportLibrary>$(ProjectDir)x86_Release\$(ProjectName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
</Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<IntrinsicFunctions>true</IntrinsicFunctions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;WIN64;_WINDOWS;_USRDLL;UNICODE_INPUT_PLUGIN;DO_LAYER12;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ImportLibrary>$(ProjectDir)x64_Release\$(ProjectName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
</Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="adts_mpg123.cpp" />
<ClCompile Include="avi_mp3_decoder.cpp" />
<ClCompile Include="flv_mp3_decoder.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="mkv_mp3_decoder.cpp" />
<ClCompile Include="mp3_in_mp4.cpp" />
<ClCompile Include="MP4Factory.cpp" />
<ClCompile Include="NSVFactory.cpp" />
<ClCompile Include="nsvmain.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="adts_mpg123.h" />
<ClInclude Include="api__mp3-mpg123.h" />
<ClInclude Include="avi_mp3_decoder.h" />
<ClInclude Include="flv_mp3_decoder.h" />
<ClInclude Include="mkv_mp3_decoder.h" />
<ClInclude Include="mp3_in_mp4.h" />
<ClInclude Include="MP4Factory.h" />
<ClInclude Include="NSVFactory.h" />
<ClInclude Include="nsvmain.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="mp3-mpg123.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\nsutil\nsutil.vcxproj">
<Project>{dabe6307-f8dd-416d-9dac-673e2decb73f}</Project>
</ProjectReference>
<ProjectReference Include="..\Wasabi\Wasabi.vcxproj">
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="adts_mpg123.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="avi_mp3_decoder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="flv_mp3_decoder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mkv_mp3_decoder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mp3_in_mp4.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MP4Factory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NSVFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="nsvmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="adts_mpg123.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="api__mp3-mpg123.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="avi_mp3_decoder.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="flv_mp3_decoder.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mkv_mp3_decoder.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mp3_in_mp4.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MP4Factory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NSVFactory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="nsvmain.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{79507766-5017-442a-906a-8d825464d222}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{4c991c0c-1c76-493f-99dc-ec1203032027}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{520e8828-1621-41d6-98df-ec2d1beec790}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="mp3-mpg123.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,228 @@
// used to decode an MPEG-1 audio object in an MPEG-4 ISO Media file
#include "mp3_in_mp4.h"
#include "api__mp3-mpg123.h"
#include "../nsutil/pcm.h"
// {B6CB4A7C-A8D0-4c55-8E60-9F7A7A23DA0F}
static const GUID playbackConfigGroupGUID =
{ 0xb6cb4a7c, 0xa8d0, 0x4c55, { 0x8e, 0x60, 0x9f, 0x7a, 0x7a, 0x23, 0xda, 0xf } };
#define FHG_DELAY 529
MPEG4_MP3::MPEG4_MP3()
{
channels = 0;
gain = 1;
floatingPoint = false;
decoder = 0;
sample_rate = 0;
bits = 16;
pregap = FHG_DELAY;
}
MPEG4_MP3::~MPEG4_MP3()
{
if (decoder) {
mpg123_delete(decoder);
decoder = 0;
}
}
int MPEG4_MP3::OpenEx(size_t _bits, size_t _maxChannels, bool useFloat)
{
_bits = bits;
floatingPoint = useFloat;
if (floatingPoint)
bits = 32;
else
bits = (int)_bits;
decoder = mpg123_new(NULL, NULL);
long flags = MPG123_QUIET|MPG123_FORCE_FLOAT|MPG123_SKIP_ID3V2|MPG123_IGNORE_STREAMLENGTH|MPG123_IGNORE_INFOFRAME;
if (_maxChannels == 1) {
flags |= MPG123_FORCE_MONO;
}
mpg123_param(decoder, MPG123_FLAGS, flags, 0);
mpg123_param(decoder, MPG123_RVA, MPG123_RVA_OFF, 0);
mpg123_open_feed(decoder);
return MP4_SUCCESS;
}
const char *MPEG4_MP3::GetCodecInfoString()
{
return 0;
}
int MPEG4_MP3::CanHandleCodec(const char *codecName)
{
if (!lstrcmpA(codecName, "mp4a"))
return 1;
else
return 0;
}
int MPEG4_MP3::CanHandleType(unsigned __int8 type)
{
switch(type)
{
case MP4_MPEG4_LAYER3_AUDIO:
case MP4_MPEG4_LAYER2_AUDIO:
case MP4_MPEG4_LAYER1_AUDIO:
case MP4_TYPE_MPEG1_AUDIO:
case MP4_TYPE_MPEG2_AUDIO:
//case MP4_TYPE_MPEG4_AUDIO:
return 1;
default:
return 0;
}
}
int MPEG4_MP3::DecodeSample(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
{
if (!decoder)
return MP4_FAILURE;
*outputBufferBytes = 0;
mpg123_feed(decoder, (unsigned char *)inputBuffer, inputBufferBytes);
for (;;) {
// get the decoded data out
size_t pcm_buf_used=0;
float decodeBuf[1152*2];
int err = mpg123_read(decoder, (unsigned char *)decodeBuf, sizeof(decodeBuf), &pcm_buf_used);
if (pcm_buf_used) {
if (!_UpdateProperties()) {
return MP4_FAILURE;
}
// deal with pregap
int numSamples = (int)pcm_buf_used / sizeof(float);
int offset = min(numSamples, pregap * channels);
numSamples -= offset;
pregap -= offset / channels;
float *pcm_buf = decodeBuf + offset;
// convert to destination sample format
nsutil_pcm_FloatToInt_Interleaved(outputBuffer, pcm_buf, bits, numSamples);
*outputBufferBytes += numSamples * bits / 8;
outputBuffer = (char *)outputBuffer + numSamples * bits / 8;
return MP4_SUCCESS;
} else if (err == MPG123_NEED_MORE) {
*outputBufferBytes = 0;
return MP4_NEED_MORE_INPUT;
} else if (err == MPG123_NEW_FORMAT) {
continue;
} else if (err == MPG123_OK) {
continue;
}
else
return MP4_FAILURE;
}
return MP4_SUCCESS;
}
bool MPEG4_MP3::_UpdateProperties()
{
if (decoder && (!channels || !sample_rate)) {
long sample_rate = 44100;
int channels = 2;
int encoding = 0;
if (mpg123_getformat(decoder, &sample_rate, &channels, &encoding) == MPG123_OK) {
this->channels = channels;
this->sample_rate = sample_rate;
}
}
return channels && sample_rate;
}
int MPEG4_MP3::GetOutputPropertiesEx(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat)
{
if (_UpdateProperties()) {
*sampleRate = this->sample_rate;
*channels = this->channels;
*bitsPerSample = bits;
*isFloat = floatingPoint;
return MP4_SUCCESS;
} else {
return MP4_FAILURE;
}
}
int MPEG4_MP3::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample)
{
bool dummy;
return GetOutputPropertiesEx(sampleRate, channels, bitsPerSample, &dummy);
}
void MPEG4_MP3::Close()
{
if (decoder) {
mpg123_delete(decoder);
decoder = 0;
}
}
void MPEG4_MP3::Flush()
{
mpg123_open_feed(decoder);
pregap = FHG_DELAY;
}
int MPEG4_MP3::SetGain(float _gain)
{
gain = _gain;
return MP4_SUCCESS;
}
int MPEG4_MP3::GetCurrentBitrate(unsigned int *bitrate)
{
mpg123_frameinfo frameInfo;
if (mpg123_info(decoder, &frameInfo) == MPG123_OK) {
*bitrate = frameInfo.bitrate;
return MP4_SUCCESS;
} else {
return MP4_FAILURE;
}
}
int MPEG4_MP3::OutputFrameSize(size_t *frameSize)
{
if (_UpdateProperties()) {
*frameSize = (bits/8) * channels * mpg123_spf(decoder);
return MP4_SUCCESS;
} else {
return MP4_FAILURE;
}
}
int MPEG4_MP3::CanHandleMPEG4Type(unsigned __int8 type)
{
switch (type)
{
case MP4_MPEG4_LAYER1_AUDIO:
case MP4_MPEG4_LAYER2_AUDIO:
case MP4_MPEG4_LAYER3_AUDIO:
return 1;
default:
return 0;
}
}
#define CBCLASS MPEG4_MP3
START_DISPATCH;
CB(MPEG4_AUDIO_OPEN_EX, OpenEx)
CB(MPEG4_AUDIO_CODEC_INFO_STRING, GetCodecInfoString)
CB(MPEG4_AUDIO_BITRATE, GetCurrentBitrate)
CB(MPEG4_AUDIO_FRAMESIZE, OutputFrameSize)
CB(MPEG4_AUDIO_OUTPUTINFO, GetOutputProperties)
CB(MPEG4_AUDIO_OUTPUTINFO_EX, GetOutputPropertiesEx)
CB(MPEG4_AUDIO_DECODE, DecodeSample)
VCB(MPEG4_AUDIO_FLUSH, Flush)
VCB(MPEG4_AUDIO_CLOSE, Close)
CB(MPEG4_AUDIO_HANDLES_CODEC, CanHandleCodec)
CB(MPEG4_AUDIO_HANDLES_TYPE, CanHandleType)
CB(MPEG4_AUDIO_HANDLES_MPEG4_TYPE, CanHandleMPEG4Type)
CB(MPEG4_AUDIO_SET_GAIN, SetGain)
END_DISPATCH;

View File

@ -0,0 +1,43 @@
#ifndef NULLSOFT_MP3_MPEG4_H
#define NULLSOFT_MP3_MPEG4_H
// used to decode an MPEG-1 audio object in an MPEG-4 ISO Media file
#include "../Plugins/Input/in_mp4/mpeg4audio.h"
#include <mpg123.h>
class MPEG4_MP3 : public MP4AudioDecoder
{
public:
MPEG4_MP3();
~MPEG4_MP3();
int Open();
int OpenEx(size_t bits, size_t maxChannels, bool useFloat);
//int AudioSpecificConfiguration(void *buffer, size_t buffer_size); // reads ASC block from mp4 file
int GetCurrentBitrate(unsigned int *bitrate);
int OutputFrameSize(size_t *frameSize);
int GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample);
int GetOutputPropertiesEx(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat);
int DecodeSample(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes);
void Flush();
void Close();
const char *GetCodecInfoString();
int CanHandleCodec(const char *codecName);
int CanHandleType(unsigned __int8 type);
int CanHandleMPEG4Type(unsigned __int8 type);
int SetGain(float gain);
private:
bool _UpdateProperties();
mpg123_handle *decoder;
int bits;
int channels;
bool floatingPoint;
int sample_rate;
RECVS_DISPATCH;
float gain;
int pregap;
};
#endif

View File

@ -0,0 +1,93 @@
#include "../nsv/nsvlib.h"
#include "../nsv/dec_if.h"
#include "nsvmain.h"
#include "../nsutil/pcm.h"
MP3_Decoder::MP3_Decoder()
{
decoder = mpg123_new(NULL, NULL);
long flags = MPG123_QUIET|MPG123_FORCE_FLOAT|MPG123_SKIP_ID3V2|MPG123_IGNORE_STREAMLENGTH|MPG123_IGNORE_INFOFRAME;
mpg123_param(decoder, MPG123_FLAGS, flags, 0);
mpg123_param(decoder, MPG123_RVA, MPG123_RVA_OFF, 0);
memset(pcm_buf, 0, sizeof(pcm_buf));
mpg123_open_feed(decoder);
fused = 0; pcm_buf_used = 0; pcm_offs = 0;
}
int MP3_Decoder::decode(void *in, int in_len,
void *out, int *out_len,
unsigned int out_fmt[8])
{
int rval = 1;
if (fused < in_len)
{
int l = 4096;
if (l > in_len - fused) l = in_len - fused;
if (l) mpg123_feed(decoder, (unsigned char *)in + fused, l);
fused += l;
}
if (!pcm_buf_used)
{
mpg123_read(decoder, (unsigned char *)pcm_buf, sizeof(pcm_buf), &pcm_buf_used);
pcm_offs = 0;
}
if (pcm_buf_used)
{
size_t numSamples = *out_len / 2;
if (numSamples > (pcm_buf_used/sizeof(float)))
numSamples = pcm_buf_used/sizeof(float);
nsutil_pcm_FloatToInt_Interleaved(out, pcm_buf+pcm_offs, 16, numSamples);
pcm_buf_used -= numSamples*sizeof(float);
pcm_offs += (int)numSamples;
*out_len = 2*(int)numSamples;
}
else
{
if (fused >= in_len) { fused = 0; rval = 0; }
*out_len = 0;
}
mpg123_frameinfo frameInfo;
if (mpg123_info(decoder, &frameInfo) == MPG123_OK) {
int nch = (frameInfo.mode == MPG123_M_MONO)?1:2;
int srate = frameInfo.rate;
out_fmt[0] = (nch && srate) ? NSV_MAKETYPE('P', 'C', 'M', ' ') : 0;
out_fmt[1] = srate;
out_fmt[2] = nch;
out_fmt[3] = (nch && srate) ? 16 : 0;
out_fmt[4] = frameInfo.bitrate;
}
return rval;
}
void MP3_Decoder::flush()
{
fused = 0;
pcm_buf_used = 0;
pcm_offs = 0;
mpg123_open_feed(decoder);
}
extern "C"
{
__declspec(dllexport) IAudioDecoder *CreateAudioDecoder(unsigned int fmt, IAudioOutput **output)
{
switch (fmt)
{
case NSV_MAKETYPE('M', 'P', '3', ' '):
return new MP3_Decoder;
default:
return NULL;
}
}
__declspec(dllexport) void DeleteAudioDecoder(IAudioDecoder *decoder)
{
if (decoder)
delete decoder;
}
}

20
Src/mp3-mpg123/nsvmain.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <mpg123.h>
#include "../nsv/dec_if.h"
class MP3_Decoder : public IAudioDecoder
{
public:
MP3_Decoder();
~MP3_Decoder() { };
int decode(void *in, int in_len,
void *out, int *out_len,
unsigned int out_fmt[8]);
void flush();
private:
mpg123_handle *decoder;
float pcm_buf[1152*2*2];
size_t pcm_buf_used;
int pcm_offs;
int fused;
};

14
Src/mp3-mpg123/resource.h Normal file
View File

@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by mp3-mpg123.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
#include "catch.hpp"

View File

@ -0,0 +1,212 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="mp3-mpg123-test"
ProjectGUID="{DDA33B81-0A85-4BAA-9DAC-12C0EBC80CEA}"
RootNamespace="mp3mpg123test"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..;../../Wasabi;../../libmpg123/src/libmpg123"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="../../nsutil/nsutil.lib"
OutputFile="$(ProgramFiles)\Winamp\$(ProjectName).exe"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
<ProjectReference
ReferencedProjectIdentifier="{5057C6D0-F787-43EB-BA3F-8D59AB3B09D1}"
RelativePathToProject=".\mp3-mpg123.vcproj"
/>
<ProjectReference
ReferencedProjectIdentifier="{67CAA87B-7CF1-4F93-BB67-21C513F40803}"
RelativePathToProject="..\libmpg123\ports\MSVC++\2008\libmpg123\libmpg123.vcproj"
/>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\main.cpp"
>
</File>
<File
RelativePath=".\test_adts_mpg123.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\catch.hpp"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,88 @@
#include "catch.hpp"
#include "adts_mpg123.h"
class MemoryStreamer : public ifc_mpeg_stream_reader
{
public:
MemoryStreamer(){}
int Peek(void *buffer, size_t to_read, size_t *bytes_read)
{
if (to_read > this->bufferBytes) {
to_read = this->bufferBytes;
}
memcpy(buffer, this->buffer, to_read);
*bytes_read = to_read;
return adts::SUCCESS;
}
int Read(void *buffer, size_t to_read, size_t *bytes_read)
{
if (to_read > this->bufferBytes) {
to_read = this->bufferBytes;
}
memcpy(buffer, this->buffer, to_read);
this->buffer = (unsigned char *)this->buffer + *bytes_read;
*bytes_read = to_read;
bufferBytes -= to_read;
return adts::SUCCESS;
}
int EndOf()
{
if (bufferBytes == 0) {
return 1;
} else {
return 0;
}
}
float GetGain()
{
return 1.0;
}
unsigned char *buffer;
size_t bufferBytes;
RECVS_DISPATCH;
};
#define CBCLASS MemoryStreamer
START_DISPATCH;
CB(MPEGSTREAM_PEEK, Peek)
CB(MPEGSTREAM_READ, Read)
CB(MPEGSTREAM_EOF, EndOf)
CB(MPEGSTREAM_GAIN, GetGain)
END_DISPATCH;
#undef CBCLASS
static const unsigned char mp3_frame1[] = {
0xFF, 0xF3, 0x70, 0x54, 0x00, 0x10, 0x2D, 0xFA, 0x96, 0x0F, 0xA0, 0x20,
0x00, 0x81, 0xE8, 0x05, 0x2C, 0x1F, 0x40, 0x00, 0x00, 0x03, 0x51, 0xB6,
0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3,
0x0B, 0x05, 0x86, 0x07, 0x60, 0x2E, 0x11, 0x94, 0x0A, 0x01, 0x61, 0xA0,
0xD0, 0xC2, 0xC5, 0xCF, 0x81, 0x41, 0x43, 0x2F, 0x44, 0x4E, 0x6E, 0x1F,
0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x01, 0xA0, 0xA2, 0x8B, 0x87, 0xF6, 0x2E,
0x7A, 0x0A, 0x19, 0x25, 0x9F, 0x02, 0xF6, 0x40, 0xA1, 0x92, 0x2E, 0x2E,
0x7F, 0xEE, 0xFF, 0x96, 0x1E, 0x0E, 0x2C, 0x1B, 0x87, 0xEC, 0x1C, 0x07,
0x8A, 0x1C, 0x18, 0x58, 0x76, 0x7C, 0x0A, 0x07, 0x86, 0x5E, 0x88, 0x94,
0xEF, 0x02, 0xF6, 0x82, 0x86, 0x49, 0x67, 0xC0, 0xBD, 0x90, 0x28, 0x64,
0x8B, 0x8B, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC,
0x3D, 0xA0, 0xA2, 0x4B, 0x8B, 0x8B, 0x8A, 0x51, 0x60, 0xDC, 0x5D, 0x85,
0x03, 0xC3, 0x2C, 0x00, 0x03, 0x31, 0xE0, 0x00, 0x7F};
TEST_CASE("", "[adts_mpg123]") {
mpg123_init();
ADTS_MPG123 mp3;
MemoryStreamer memoryStreamer;
REQUIRE(mp3.Initialize(false, false, false, 16, true, true, true) == adts::SUCCESS);
REQUIRE(mp3.Open(&memoryStreamer) == true);
size_t numBits;
size_t numChannels;
int sampleRate;
memoryStreamer.buffer = (unsigned char *)mp3_frame1;
memoryStreamer.bufferBytes = sizeof(mp3_frame1);
size_t outputWritten=777;
size_t bitrate=777;
REQUIRE(mp3.Sync(&memoryStreamer, 0, 0, &outputWritten, &bitrate) == adts::SUCCESS);
REQUIRE(bitrate == 64);
REQUIRE(outputWritten == 0);
}

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "../Winamp/buildType.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION WINAMP_PRODUCTVER
PRODUCTVERSION WINAMP_PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Winamp SA"
VALUE "FileDescription", "Winamp 5.x System Component"
VALUE "FileVersion", STR_WINAMP_PRODUCTVER
VALUE "InternalName", "mp3.w5s"
VALUE "LegalCopyright", "Copyright <20> 2015-2023 Ben Allison"
VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
VALUE "OriginalFilename", "mp3.w5s"
VALUE "ProductName", "Winamp MPEG Audio Decoder Service"
VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END