Commit 0714ddb8 authored by nanahira's avatar nanahira

ikpmp3 in

parent 74d85026
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
/event /event
/freetype /freetype
/sqlite3 /sqlite3
/ikpmp3
/irrklang /irrklang
/irrlicht /irrlicht
......
// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "irrKlang" library.
// For conditions of distribution and use, see copyright notice in irrKlang.h
#include "CIrrKlangAudioStreamLoaderMP3.h"
#include "CIrrKlangAudioStreamMP3.h"
#include <string.h>
namespace irrklang
{
CIrrKlangAudioStreamLoaderMP3::CIrrKlangAudioStreamLoaderMP3()
{
}
//! Returns true if the file maybe is able to be loaded by this class.
bool CIrrKlangAudioStreamLoaderMP3::isALoadableFileExtension(const ik_c8* fileName)
{
return strstr(fileName, ".mp3") != 0;
}
//! Creates an audio file input stream from a file
IAudioStream* CIrrKlangAudioStreamLoaderMP3::createAudioStream(irrklang::IFileReader* file)
{
CIrrKlangAudioStreamMP3* stream = new CIrrKlangAudioStreamMP3(file);
if (stream && !stream->isOK())
{
stream->drop();
stream = 0;
}
return stream;
}
} // end namespace irrklang
// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "irrKlang" library.
// For conditions of distribution and use, see copyright notice in irrKlang.h
#ifndef __C_IRRKLANG_AUDIO_STREAM_LOADER_MP3_H_INCLUDED__
#define __C_IRRKLANG_AUDIO_STREAM_LOADER_MP3_H_INCLUDED__
#include <ik_IAudioStreamLoader.h>
namespace irrklang
{
//! Class which is able to create an audio file stream from a file.
class CIrrKlangAudioStreamLoaderMP3 : public IAudioStreamLoader
{
public:
CIrrKlangAudioStreamLoaderMP3();
//! Returns true if the file maybe is able to be loaded by this class.
/** This decision should be based only on the file extension (e.g. ".wav") */
virtual bool isALoadableFileExtension(const ik_c8* fileName);
//! Creates an audio file input stream from a file
/** \return Pointer to the created audio stream. Returns 0 if loading failed.
If you no longer need the stream, you should call IAudioFileStream::drop().
See IRefCounted::drop() for more information. */
virtual IAudioStream* createAudioStream(irrklang::IFileReader* file);
};
} // end namespace irrklang
#endif
// Copyright (C) 2002-2007 Nikolaus Gebhardt
// Part of the code for this plugin for irrKlang is based on:
// MP3 input for Audiere by Matt Campbell <mattcampbell@pobox.com>, based on
// libavcodec from ffmpeg (http://ffmpeg.sourceforge.net/).
// See license.txt for license details of this plugin.
#include "CIrrKlangAudioStreamMP3.h"
#include <memory.h>
#include <stdlib.h> // free, malloc and realloc
#include <string.h>
#include <algorithm>
namespace irrklang
{
CIrrKlangAudioStreamMP3::CIrrKlangAudioStreamMP3(IFileReader* file)
: File(file), TheMPAuDecContext(0), InputPosition(0), InputLength(0),
DecodeBuffer(0), FirstFrameRead(false), EndOfFileReached(0),
FileBegin(0), Position(0)
{
if (File)
{
File->grab();
TheMPAuDecContext = new MPAuDecContext();
if (!TheMPAuDecContext || mpaudec_init(TheMPAuDecContext) < 0)
{
File->drop();
File = 0;
delete TheMPAuDecContext;
TheMPAuDecContext = 0;
return;
}
// init, get format
DecodeBuffer = new ik_u8[MPAUDEC_MAX_AUDIO_FRAME_SIZE];
if (File->getSize()>0)
{
// seekable file, now parse file to get size
// (needed to make it possible for the engine to loop a stream correctly)
skipID3IfNecessary();
TheMPAuDecContext->parse_only = 1;
Format.FrameCount = 0;
while(!EndOfFileReached)
{
if (!decodeFrame())
break;
Format.FrameCount += TheMPAuDecContext->frame_size;
if (!EndOfFileReached /*&& File->isSeekable()*/ )
{
// to be able to seek in the stream, store offsets and sizes
SFramePositionData data;
data.size = TheMPAuDecContext->frame_size;
data.offset = File->getPos() - (InputLength - InputPosition) - TheMPAuDecContext->coded_frame_size;
FramePositionData.push_back(data);
}
}
TheMPAuDecContext->parse_only = 0;
setPosition(0);
}
else
decodeFrame(); // decode first frame to read audio format
if (!TheMPAuDecContext->channels ||
!TheMPAuDecContext->sample_rate )
{
File->drop();
File = 0;
delete TheMPAuDecContext;
TheMPAuDecContext = 0;
return;
}
}
}
CIrrKlangAudioStreamMP3::~CIrrKlangAudioStreamMP3()
{
if (File)
File->drop();
if (TheMPAuDecContext)
{
mpaudec_clear(TheMPAuDecContext);
delete TheMPAuDecContext;
}
delete [] DecodeBuffer;
}
//! returns format of the audio stream
SAudioStreamFormat CIrrKlangAudioStreamMP3::getFormat()
{
return Format;
}
//! tells the audio stream to read n audio frames into the specified buffer
ik_s32 CIrrKlangAudioStreamMP3::readFrames(void* target, ik_s32 frameCountToRead)
{
const int frameSize = Format.getFrameSize();
int framesRead = 0;
ik_u8* out = (ik_u8*)target;
while (framesRead < frameCountToRead)
{
// no more samples? ask the MP3 for more
if (DecodedQueue.getSize() < frameSize)
{
if (!decodeFrame() || EndOfFileReached)
return framesRead;
// if the buffer is still empty, we are done
if (DecodedQueue.getSize() < frameSize)
return framesRead;
}
const int framesLeft = frameCountToRead - framesRead;
const int dequeSize = DecodedQueue.getSize() / frameSize;
const int framesToRead = framesLeft < dequeSize ? framesLeft : dequeSize;
DecodedQueue.read(out, framesToRead * frameSize);
out += framesToRead * frameSize;
framesRead += framesToRead;
Position += framesToRead;
}
return framesRead;
}
bool CIrrKlangAudioStreamMP3::decodeFrame()
{
int outputSize = 0;
while (!outputSize)
{
if (InputPosition == InputLength)
{
InputPosition = 0;
InputLength = File->read(InputBuffer, IKP_MP3_INPUT_BUFFER_SIZE);
if (InputLength == 0)
{
EndOfFileReached = true;
return true;
}
}
int rv = mpaudec_decode_frame( TheMPAuDecContext, (ik_s16*)DecodeBuffer,
&outputSize,
(ik_u8*)InputBuffer + InputPosition,
InputLength - InputPosition);
if (rv < 0)
return false;
InputPosition += rv;
} // end while
if (!FirstFrameRead)
{
Format.ChannelCount = TheMPAuDecContext->channels;
Format.SampleRate = TheMPAuDecContext->sample_rate;
Format.SampleFormat = ESF_S16;
Format.FrameCount = -1; // unknown lenght
FirstFrameRead = true;
}
else
if (TheMPAuDecContext->channels != Format.ChannelCount ||
TheMPAuDecContext->sample_rate != Format.SampleRate)
{
// Can't handle format changes mid-stream.
return false;
}
if (!TheMPAuDecContext->parse_only)
{
if (outputSize < 0)
{
// Couldn't decode this frame. Too bad, already lost it.
// This should only happen when seeking.
outputSize = TheMPAuDecContext->frame_size;
memset(DecodeBuffer, 0, outputSize * Format.getFrameSize());
}
DecodedQueue.write(DecodeBuffer, outputSize);
}
return true;
}
//! sets the position of the audio stream.
/** For example to let the stream be read from the beginning of the file again,
setPosition(0) would be called. This is usually done be the sound engine to
loop a stream after if has reached the end. Return true if sucessful and 0 if not. */
bool CIrrKlangAudioStreamMP3::setPosition(ik_s32 pos)
{
if (!File || !TheMPAuDecContext)
return false;
if (pos == 0)
{
// usually done for looping, just reset to start
File->seek(FileBegin); // skip possible ID3 header
EndOfFileReached = false;
DecodedQueue.clear();
MPAuDecContext oldContext = *TheMPAuDecContext;
mpaudec_clear(TheMPAuDecContext);
mpaudec_init(TheMPAuDecContext);
TheMPAuDecContext->bit_rate = oldContext.bit_rate;
TheMPAuDecContext->channels = oldContext.channels;
TheMPAuDecContext->frame_size = oldContext.frame_size;
TheMPAuDecContext->sample_rate = oldContext.sample_rate;
InputPosition = 0;
InputLength = 0;
Position = 0;
CurrentFramePosition = 0;
return true;
}
else
{
// user wants to seek in the stream, so do this here
int scan_position = 0;
int target_frame = 0;
int frame_count = (int)FramePositionData.size();
while (target_frame < frame_count)
{
int frame_size = FramePositionData[target_frame].size;
if (pos <= scan_position + frame_size)
break;
else
{
scan_position += frame_size;
target_frame++;
}
}
const int MAX_FRAME_DEPENDENCY = 10;
target_frame = std::max(0, target_frame - MAX_FRAME_DEPENDENCY);
setPosition(0);
File->seek(FramePositionData[target_frame].offset, false);
int i;
for (i = 0; i < target_frame; i++)
{
if (i>=(int)FramePositionData.size())
{
// internal error
setPosition(0);
return false;
}
Position += FramePositionData[i].size;
}
if (!decodeFrame() || EndOfFileReached)
{
setPosition(0);
return false;
}
int frames_to_consume = pos - Position; // PCM frames now
if (frames_to_consume > 0)
{
ik_u8 *buf = new ik_u8[frames_to_consume * Format.getFrameSize()];
readFrames(buf, frames_to_consume);
delete[] buf;
}
return true;
}
return false;
}
CIrrKlangAudioStreamMP3::QueueBuffer::QueueBuffer()
{
Capacity = 256;
Size = 0;
Buffer = (ik_u8*)malloc(Capacity);
}
CIrrKlangAudioStreamMP3::QueueBuffer::~QueueBuffer()
{
free(Buffer);
}
int CIrrKlangAudioStreamMP3::QueueBuffer::getSize()
{
return Size;
}
void CIrrKlangAudioStreamMP3::QueueBuffer::write(const void* buffer, int size)
{
bool needRealloc = false;
while (size + Size > Capacity)
{
Capacity *= 2;
needRealloc = true;
}
if (needRealloc)
{
Buffer = (ik_u8*)realloc(Buffer, Capacity);
}
memcpy(Buffer + Size, buffer, size);
Size += size;
}
int CIrrKlangAudioStreamMP3::QueueBuffer::read(void* buffer, int size)
{
int toRead = size < Size ? size : Size;
memcpy(buffer, Buffer, toRead);
memmove(Buffer, Buffer + toRead, Size - toRead);
Size -= toRead;
return toRead;
}
void CIrrKlangAudioStreamMP3::QueueBuffer::clear()
{
Size = 0;
}
void CIrrKlangAudioStreamMP3::skipID3IfNecessary()
{
char header[10];
int read = File->read(&header, 10);
if (read == 10 &&
header[0] == 'I' && header[1] == 'D' && header[2] == '3')
{
int versionMajor = header[3];
int versionMinor = header[4];
int flags = header[5];
// IDv2 size looks like the following: ID3v2 size 4 * %0xxxxxxx.
// Sick, but that's how it works.
int size = 0;
size = (header[6] & 0x7f) << (3*7);
size |= (header[7] & 0x7f) << (2*7);
size |= (header[8] & 0x7f) << (1*7);
size |= (header[9] & 0x7f) ;
size += 10; // header size
FileBegin = size;
File->seek(FileBegin);
}
else
File->seek(0);
}
} // end namespace irrklang
// Copyright (C) 2002-2007 Nikolaus Gebhardt
// Part of the code for this plugin for irrKlang is based on:
// MP3 input for Audiere by Matt Campbell <mattcampbell@pobox.com>, based on
// libavcodec from ffmpeg (http://ffmpeg.sourceforge.net/).
// See license.txt for license details of this plugin.
#ifndef __C_IRRKLANG_AUDIO_STREAM_MP3_H_INCLUDED__
#define __C_IRRKLANG_AUDIO_STREAM_MP3_H_INCLUDED__
#include <ik_IAudioStream.h>
#include <ik_IFileReader.h>
#include <vector>
#include "decoder/mpaudec.h"
namespace irrklang
{
const int IKP_MP3_INPUT_BUFFER_SIZE = 4096;
//! Reads and decodes audio data into an usable audio stream for the ISoundEngine
/** To extend irrKlang with new audio format decoders, the only thing needed to do
is implementing the IAudioStream interface. All the code available in this class is only for
mp3 decoding and may make this class look a bit more complicated then it actually is. */
class CIrrKlangAudioStreamMP3 : public IAudioStream
{
public:
CIrrKlangAudioStreamMP3(IFileReader* file);
~CIrrKlangAudioStreamMP3();
//! returns format of the audio stream
virtual SAudioStreamFormat getFormat();
//! tells the audio stream to read n audio frames into the specified buffer
/** \param target: Target data buffer to the method will write the read frames into. The
specified buffer will be getFormat().getFrameSize()*frameCount big.
\param frameCount: amount of frames to be read.
\returns Returns amount of frames really read. Should be frameCountToRead in most cases. */
virtual ik_s32 readFrames(void* target, ik_s32 frameCountToRead);
//! sets the position of the audio stream.
/** For example to let the stream be read from the beginning of the file again,
setPosition(0) would be called. This is usually done be the sound engine to
loop a stream after if has reached the end. Return true if sucessful and 0 if not. */
virtual bool setPosition(ik_s32 pos);
// just for the CIrrKlangAudioStreamLoaderMP3 to let him know if loading worked
bool isOK() { return File != 0; }
protected:
ik_s32 readFrameForMP3(void* target, ik_s32 frameCountToRead, bool parseOnly=false);
bool decodeFrame();
void skipID3IfNecessary();
irrklang::IFileReader* File;
SAudioStreamFormat Format;
// mpaudec specific
MPAuDecContext* TheMPAuDecContext;
ik_u8 InputBuffer[IKP_MP3_INPUT_BUFFER_SIZE];
int InputPosition;
int InputLength;
int Position;
ik_u8* DecodeBuffer;
ik_s32 FileBegin;
ik_u32 CurrentFramePosition;
bool FirstFrameRead;
bool EndOfFileReached;
// helper class for managing the streaming decoded audio data
class QueueBuffer
{
public:
QueueBuffer();
~QueueBuffer();
int getSize();
void write(const void* buffer, int size);
int read(void* buffer, int size);
void clear();
private:
ik_u8* Buffer;
int Capacity;
int Size;
};
struct SFramePositionData
{
int offset;
int size;
};
std::vector<SFramePositionData> FramePositionData;
QueueBuffer DecodedQueue;
};
} // end namespace irrklang
#endif
/*
* Common bit i/o utils
* Copyright (c) 2000, 2001 Fabrice Bellard.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Modified by Matt Campbell <mattcampbell@pobox.com> for the stand-alone
* mpaudec library. Based on common.c from libavcodec.
*/
#include "internal.h"
/**
* init GetBitContext.
* @param buffer bitstream buffer
* @param bit_size the size of the buffer in bits
*/
void init_get_bits(GetBitContext *s,
const uint8_t *buffer, int bit_size)
{
s->buffer= buffer;
s->size_in_bits= bit_size;
s->index=0;
}
unsigned int show_bits(const GetBitContext *s, int n)
{
int i;
unsigned int result = 0;
assert(s->size_in_bits - s->index >= n);
for (i = s->index; i < s->index + n; i++) {
int byte_index = i / 8;
unsigned int right_shift = 7 - (i % 8);
uint8_t byte = s->buffer[byte_index];
uint8_t bit;
result <<= 1;
if (right_shift == 0)
bit = byte & 0x1;
else
bit = (byte >> right_shift) & 0x1;
result |= (unsigned int)bit;
}
return result;
}
void skip_bits(GetBitContext *s, int n)
{
s->index += n;
}
unsigned int get_bits(GetBitContext *s, int n)
{
unsigned int result = show_bits(s, n);
skip_bits(s, n);
return result;
}
int get_bits_count(const GetBitContext *s)
{
return s->index;
}
/* VLC decoding */
/*#define DEBUG_VLC*/
#define GET_DATA(v, table, i, wrap, size) \
{\
const uint8_t *ptr = (const uint8_t *)table + i * wrap;\
switch(size) {\
case 1:\
v = *(const uint8_t *)ptr;\
break;\
case 2:\
v = *(const uint16_t *)ptr;\
break;\
default:\
v = *(const uint32_t *)ptr;\
break;\
}\
}
static int alloc_table(VLC *vlc, int size)
{
int index;
index = vlc->table_size;
vlc->table_size += size;
if (vlc->table_size > vlc->table_allocated) {
vlc->table_allocated += (1 << vlc->bits);
vlc->table = realloc(vlc->table,
sizeof(VLC_TYPE) * 2 * vlc->table_allocated);
if (!vlc->table)
return -1;
}
return index;
}
static int build_table(VLC *vlc, int table_nb_bits,
int nb_codes,
const void *bits, int bits_wrap, int bits_size,
const void *codes, int codes_wrap, int codes_size,
uint32_t code_prefix, int n_prefix)
{
int i, j, k, n, table_size, table_index, nb, n1, index;
uint32_t code;
VLC_TYPE (*table)[2];
table_size = 1 << table_nb_bits;
table_index = alloc_table(vlc, table_size);
#ifdef DEBUG_VLC
printf("new table index=%d size=%d code_prefix=%x n=%d\n",
table_index, table_size, code_prefix, n_prefix);
#endif
if (table_index < 0)
return -1;
table = &vlc->table[table_index];
for(i=0;i<table_size;i++) {
table[i][1] = 0; /*bits*/
table[i][0] = -1; /*codes*/
}
/* first pass: map codes and compute auxillary table sizes */
for(i=0;i<nb_codes;i++) {
GET_DATA(n, bits, i, bits_wrap, bits_size);
GET_DATA(code, codes, i, codes_wrap, codes_size);
/* we accept tables with holes */
if (n <= 0)
continue;
#if defined(DEBUG_VLC) && 0
printf("i=%d n=%d code=0x%x\n", i, n, code);
#endif
/* if code matches the prefix, it is in the table */
n -= n_prefix;
if (n > 0 && (code >> n) == code_prefix) {
if (n <= table_nb_bits) {
/* no need to add another table */
j = (code << (table_nb_bits - n)) & (table_size - 1);
nb = 1 << (table_nb_bits - n);
for(k=0;k<nb;k++) {
#ifdef DEBUG_VLC
printf("%4x: code=%d n=%d\n",
j, i, n);
#endif
assert(table[j][1] /*bits*/ == 0);
table[j][1] = n; /*bits*/
table[j][0] = i; /*code*/
j++;
}
} else {
n -= table_nb_bits;
j = (code >> n) & ((1 << table_nb_bits) - 1);
#ifdef DEBUG_VLC
printf("%4x: n=%d (subtable)\n",
j, n);
#endif
/* compute table size */
n1 = -table[j][1]; /*bits*/
if (n > n1)
n1 = n;
table[j][1] = -n1; /*bits*/
}
}
}
/* second pass : fill auxillary tables recursively */
for(i=0;i<table_size;i++) {
n = table[i][1]; /*bits*/
if (n < 0) {
n = -n;
if (n > table_nb_bits) {
n = table_nb_bits;
table[i][1] = -n; /*bits*/
}
index = build_table(vlc, n, nb_codes,
bits, bits_wrap, bits_size,
codes, codes_wrap, codes_size,
(code_prefix << table_nb_bits) | i,
n_prefix + table_nb_bits);
if (index < 0)
return -1;
/* note: realloc has been done, so reload tables */
table = &vlc->table[table_index];
table[i][0] = index; /*code*/
}
}
return table_index;
}
/* Build VLC decoding tables suitable for use with get_vlc().
'nb_bits' set thee decoding table size (2^nb_bits) entries. The
bigger it is, the faster is the decoding. But it should not be too
big to save memory and L1 cache. '9' is a good compromise.
'nb_codes' : number of vlcs codes
'bits' : table which gives the size (in bits) of each vlc code.
'codes' : table which gives the bit pattern of of each vlc code.
'xxx_wrap' : give the number of bytes between each entry of the
'bits' or 'codes' tables.
'xxx_size' : gives the number of bytes of each entry of the 'bits'
or 'codes' tables.
'wrap' and 'size' allows to use any memory configuration and types
(byte/word/long) to store the 'bits' and 'codes' tables.
*/
int init_vlc(VLC *vlc, int nb_bits, int nb_codes,
const void *bits, int bits_wrap, int bits_size,
const void *codes, int codes_wrap, int codes_size)
{
vlc->bits = nb_bits;
vlc->table = NULL;
vlc->table_allocated = 0;
vlc->table_size = 0;
#ifdef DEBUG_VLC
printf("build table nb_codes=%d\n", nb_codes);
#endif
if (build_table(vlc, nb_bits, nb_codes,
bits, bits_wrap, bits_size,
codes, codes_wrap, codes_size,
0, 0) < 0) {
free(vlc->table);
return -1;
}
return 0;
}
void free_vlc(VLC *vlc)
{
free(vlc->table);
}
int get_vlc(GetBitContext *s, const VLC *vlc)
{
int code = 0;
int depth = 0, max_depth = 3;
int n, index, bits = vlc->bits;
do {
index = show_bits(s, bits) + code;
code = vlc->table[index][0];
n = vlc->table[index][1];
depth++;
if (n < 0 && depth < max_depth) {
skip_bits(s, bits);
bits = -n;
}
} while (n < 0 && depth < max_depth);
skip_bits(s, n);
return code;
}
/* Based on common.h from libavcodec. Modified extensively by Matt Campbell
<mattcampbell@pobox.com> for the stand-alone mpaudec library. */
#ifndef INTERNAL_H
#define INTERNAL_H
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
# define CONFIG_WIN32
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stddef.h>
#include "mpaudec.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifdef CONFIG_WIN32
/* windows */
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned __int64 uint64_t;
typedef signed char int8_t;
typedef signed int int32_t;
typedef signed __int64 int64_t;
# ifdef _DEBUG
# define DEBUG
# endif
/* CONFIG_WIN32 end */
#else
/* unix */
#include <inttypes.h>
#endif /* !CONFIG_WIN32 */
/* debug stuff */
#if !defined(DEBUG) && !defined(NDEBUG)
# define NDEBUG
#endif
#include <assert.h>
/* bit input */
typedef struct GetBitContext {
const uint8_t *buffer;
int index;
int size_in_bits;
} GetBitContext;
int get_bits_count(const GetBitContext *s);
#define VLC_TYPE int16_t
typedef struct VLC {
int bits;
VLC_TYPE (*table)[2];
int table_size, table_allocated;
} VLC;
unsigned int get_bits(GetBitContext *s, int n);
unsigned int show_bits(const GetBitContext *s, int n);
void skip_bits(GetBitContext *s, int n);
void init_get_bits(GetBitContext *s,
const uint8_t *buffer, int buffer_size);
int init_vlc(VLC *vlc, int nb_bits, int nb_codes,
const void *bits, int bits_wrap, int bits_size,
const void *codes, int codes_wrap, int codes_size);
void free_vlc(VLC *vlc);
int get_vlc(GetBitContext *s, const VLC *vlc);
#endif /* INTERNAL_H */
This diff is collapsed.
/* Portions based on avcodec.h from libavcodec. */
#ifndef MPAUDEC_H
#define MPAUDEC_H
#ifdef __cplusplus
extern "C" {
#endif
/* in bytes */
#define MPAUDEC_MAX_AUDIO_FRAME_SIZE 4608
typedef struct MPAuDecContext {
int bit_rate;
int layer;
int sample_rate;
int channels;
int frame_size;
void *priv_data;
int parse_only;
int coded_frame_size;
} MPAuDecContext;
int mpaudec_init(MPAuDecContext *mpctx);
int mpaudec_decode_frame(MPAuDecContext * mpctx,
void *data, int *data_size,
const unsigned char * buf, int buf_size);
void mpaudec_clear(MPAuDecContext *mpctx);
#ifdef __cplusplus
}
#endif
#endif /* MPAUDEC_H */
This diff is collapsed.
/* Modified slightly by Matt Campbell <mattcampbell@pobox.com> for the
stand-alone mpaudec library. Based on mpegaudio.h from libavcodec. */
/* max frame size, in samples */
#define MPA_FRAME_SIZE 1152
/* max compressed frame size */
#define MPA_MAX_CODED_FRAME_SIZE 1792
#define MPA_MAX_CHANNELS 2
#define SBLIMIT 32 /* number of subbands */
#define MPA_STEREO 0
#define MPA_JSTEREO 1
#define MPA_DUAL 2
#define MPA_MONO 3
#include <irrKlang.h>
#include <stdio.h>
#include <string.h>
#include "CIrrKlangAudioStreamLoaderMP3.h"
using namespace irrklang;
#ifdef WIN32
// Windows version
extern "C" __declspec(dllexport) void ikpMP3Init(ISoundEngine* engine)
#else
// Linux version
extern "C" void ikpMP3Init(ISoundEngine* engine)
#endif
{
// create and register the loader
CIrrKlangAudioStreamLoaderMP3* loader = new CIrrKlangAudioStreamLoaderMP3();
engine->registerAudioStreamLoader(loader);
loader->drop();
// that's it, that's all.
}
#include <irrKlang.h>
namespace irrklang
{
#ifdef WIN32
// Windows version
extern "C" __declspec(dllexport) void ikpMP3Init(ISoundEngine* engine);
#else
// Linux version
extern "C" void ikpMP3Init(ISoundEngine* engine);
#endif
}
\ No newline at end of file
diff -ur ikpmp3/CIrrKlangAudioStreamMP3.cpp ikpmp3-static/CIrrKlangAudioStreamMP3.cpp
--- ikpmp3/CIrrKlangAudioStreamMP3.cpp 2009-01-02 07:33:40.000000000 +0800
+++ ikpmp3-static/CIrrKlangAudioStreamMP3.cpp 2017-11-27 19:18:34.295546800 +0800
@@ -8,6 +8,7 @@
#include <memory.h>
#include <stdlib.h> // free, malloc and realloc
#include <string.h>
+#include <algorithm>
namespace irrklang
{
diff -ur ikpmp3/ikpMP3.cpp ikpmp3-static/ikpMP3.cpp
--- ikpmp3/ikpMP3.cpp 2007-10-28 18:14:00.000000000 +0800
+++ ikpmp3-static/ikpMP3.cpp 2017-11-27 19:49:02.119092400 +0800
@@ -6,30 +6,14 @@
using namespace irrklang;
-// this is the only function needed to be implemented for the plugin, it gets
-// called by irrKlang when loaded.
-// In this plugin, we create an audiostream loader class and register
-// it at the engine, but a plugin can do anything.
-// Be sure to name the function 'irrKlangPluginInit' and let the dll start with 'ikp'.
-
#ifdef WIN32
// Windows version
-__declspec(dllexport) void __stdcall irrKlangPluginInit(ISoundEngine* engine, const char* version)
+extern "C" __declspec(dllexport) void ikpMP3Init(ISoundEngine* engine)
#else
// Linux version
-void irrKlangPluginInit(ISoundEngine* engine, const char* version)
+extern "C" void ikpMP3Init(ISoundEngine* engine)
#endif
{
- // do some version security check to be sure that this plugin isn't begin used
- // by some newer irrKlang version with changed interfaces which could possibily
- // cause crashes.
-
- if (strcmp(version, IRR_KLANG_VERSION))
- {
- printf("This MP3 plugin only supports irrKlang version %s, mp3 playback disabled.\n", IRR_KLANG_VERSION);
- return;
- }
-
// create and register the loader
CIrrKlangAudioStreamLoaderMP3* loader = new CIrrKlangAudioStreamLoaderMP3();
This diff is collapsed.
project "ikpmp3"
kind "StaticLib"
files { "*.cpp", "*.h", "decoder/*.c", "decoder/*.h" }
includedirs { "../irrklang/include" }
ikpMP3 is a plugin for irrKlang.
Copyright (C) 2002-2007 Nikolaus Gebhardt
Part of the code for this plugin for irrKlang is based on:
MP3 input for Audiere by Matt Campbell <mattcampbell@pobox.com>, based on
libavcodec from ffmpeg (http://ffmpeg.sourceforge.net/).
See license.txt for license details of this plugin.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment