mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
Remove native audio mixer (Unused in PPSSPP) and stb_vorbis
This commit is contained in:
parent
efbd100dd3
commit
ca0a6dc7f9
@ -423,11 +423,6 @@ add_library(rg_etc1 STATIC
|
||||
ext/native/ext/rg_etc1/rg_etc1.h)
|
||||
include_directories(ext/native/ext/rg_etc1)
|
||||
|
||||
add_library(stb_vorbis STATIC
|
||||
ext/native/ext/stb_vorbis/stb_vorbis.c
|
||||
ext/native/ext/stb_vorbis/stb_vorbis.h)
|
||||
include_directories(ext/native/ext/stb_vorbis)
|
||||
|
||||
if(USE_FFMPEG)
|
||||
if(USE_SYSTEM_FFMPEG)
|
||||
find_package(FFMPEG)
|
||||
@ -876,10 +871,6 @@ add_library(native STATIC
|
||||
${nativeExtra}
|
||||
ext/native/base/backtrace.cpp
|
||||
ext/native/base/backtrace.h
|
||||
ext/native/audio/mixer.cpp
|
||||
ext/native/audio/mixer.h
|
||||
ext/native/audio/wav_read.cpp
|
||||
ext/native/audio/wav_read.h
|
||||
ext/native/base/basictypes.h
|
||||
ext/native/base/buffer.cpp
|
||||
ext/native/base/buffer.h
|
||||
@ -1022,7 +1013,7 @@ if (LINUX AND NOT ANDROID)
|
||||
SET(RT_LIB rt)
|
||||
endif()
|
||||
|
||||
target_link_libraries(native ${LIBZIP_LIBRARY} ${ZLIB_LIBRARY} ${PNG_LIBRARY} rg_etc1 vjson stb_vorbis snappy udis86 ${RT_LIB} ${GLEW_LIBRARIES})
|
||||
target_link_libraries(native ${LIBZIP_LIBRARY} ${ZLIB_LIBRARY} ${PNG_LIBRARY} rg_etc1 vjson snappy udis86 ${RT_LIB} ${GLEW_LIBRARIES})
|
||||
|
||||
if(ANDROID)
|
||||
target_link_libraries(native log EGL)
|
||||
|
@ -36,12 +36,6 @@ SOURCES += $$P/ext/native/ext/jpge/*.cpp
|
||||
HEADERS += $$P/ext/native/ext/jpge/*.h
|
||||
INCLUDEPATH += $$P/ext/native/ext/jpge
|
||||
|
||||
# Stb_vorbis
|
||||
|
||||
SOURCES += $$P/ext/native/ext/stb_vorbis/stb_vorbis.c
|
||||
HEADERS += $$P/ext/native/ext/stb_vorbis/stb_vorbis.h
|
||||
INCLUDEPATH += $$P/ext/native/ext/stb_vorbis
|
||||
|
||||
# Snappy
|
||||
!exists( /usr/include/snappy-c.h ) {
|
||||
SOURCES += $$P/ext/snappy/*.cpp
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "file/zip_read.h"
|
||||
#include "input/input_state.h"
|
||||
#include "profiler/profiler.h"
|
||||
#include "audio/mixer.h"
|
||||
#include "math/math_util.h"
|
||||
#include "net/resolve.h"
|
||||
#include "android/jni/native_audio.h"
|
||||
|
@ -1,92 +0,0 @@
|
||||
/usr/bin/c++
|
||||
-std=gnu++0x
|
||||
CMakeFiles/ppsspp.dir/home/artart78/prog/psp/ppsspp/android/jni/NativeApp.cpp.o
|
||||
CMakeFiles/ppsspp.dir/home/artart78/prog/psp/ppsspp/android/jni/EmuScreen.cpp.o
|
||||
CMakeFiles/ppsspp.dir/home/artart78/prog/psp/ppsspp/android/jni/MenuScreens.cpp.o
|
||||
CMakeFiles/ppsspp.dir/home/artart78/prog/psp/ppsspp/android/jni/GamepadEmu.cpp.o
|
||||
CMakeFiles/ppsspp.dir/home/artart78/prog/psp/ppsspp/android/jni/UIShader.cpp.o
|
||||
CMakeFiles/ppsspp.dir/home/artart78/prog/psp/ppsspp/android/jni/ui_atlas.cpp.o
|
||||
CMakeFiles/ppsspp.dir/home/artart78/prog/psp/ppsspp/native/base/PCMain.cpp.o
|
||||
-o
|
||||
ppsspp
|
||||
-rdynamic
|
||||
-L/usr/local/lib
|
||||
-L/opt/local/lib
|
||||
-L/usr/X11/lib
|
||||
-Wl,-Bstatic
|
||||
-lSDLmain
|
||||
-Wl,-Bdynamic
|
||||
-lSDL
|
||||
-lpthread
|
||||
-lGLU
|
||||
-lGL
|
||||
-lSM
|
||||
-lICE
|
||||
-lX11
|
||||
-lXext
|
||||
-lGLEW
|
||||
kirk/libkirk.a
|
||||
file/libfile.a
|
||||
kirk/libkirk.a
|
||||
math/liblin.a
|
||||
kirk/libkirk.a
|
||||
-lpng
|
||||
kirk/libkirk.a
|
||||
-lz
|
||||
kirk/libkirk.a
|
||||
gfx/libgfx.a
|
||||
kirk/libkirk.a
|
||||
gfx_es2/libgfx_es2.a
|
||||
kirk/libkirk.a
|
||||
etcpack/libetcdec.a
|
||||
kirk/libkirk.a
|
||||
image/libimage.a
|
||||
kirk/libkirk.a
|
||||
stb_image/libstb_image.a
|
||||
kirk/libkirk.a
|
||||
audio/libmixer.a
|
||||
kirk/libkirk.a
|
||||
net/libnet.a
|
||||
kirk/libkirk.a
|
||||
ui/libui.a
|
||||
kirk/libkirk.a
|
||||
profiler/libprofiler.a
|
||||
kirk/libkirk.a
|
||||
base/libtimeutil.a
|
||||
kirk/libkirk.a
|
||||
libzip/libzip.a
|
||||
kirk/libkirk.a
|
||||
base/libbase.a
|
||||
kirk/libkirk.a
|
||||
math/liblin.a
|
||||
kirk/libkirk.a
|
||||
vjson/libvjson.a
|
||||
kirk/libkirk.a
|
||||
stb_vorbis/libstb_vorbis.a
|
||||
kirk/libkirk.a
|
||||
sha1/libsha1.a
|
||||
kirk/libkirk.a
|
||||
jsonwriter/libjsonwriter.a
|
||||
kirk/libkirk.a
|
||||
Common/libcommon.a
|
||||
kirk/libkirk.a
|
||||
Core/libcore.a
|
||||
kirk/libkirk.a
|
||||
GPU/libgpu.a
|
||||
kirk/libkirk.a
|
||||
base/libbase.a
|
||||
kirk/libkirk.a
|
||||
Common/libcommon.a
|
||||
kirk/libkirk.a
|
||||
math/liblin.a
|
||||
kirk/libkirk.a
|
||||
gfx_es2/libgfx_es2.a
|
||||
kirk/libkirk.a
|
||||
file/libfile.a
|
||||
kirk/libkirk.a
|
||||
libzip/libzip.a
|
||||
kirk/libkirk.a
|
||||
gfx/libgfx.a
|
||||
kirk/libkirk.a
|
||||
-Wl,-rpath,/usr/local/lib:/opt/local/lib:/usr/X11/lib
|
||||
|
@ -7,8 +7,6 @@ include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := libnative
|
||||
LOCAL_ARM_MODE := arm
|
||||
LOCAL_SRC_FILES :=\
|
||||
audio/wav_read.cpp \
|
||||
audio/mixer.cpp.arm \
|
||||
base/backtrace.cpp \
|
||||
base/buffer.cpp \
|
||||
base/compat.cpp \
|
||||
@ -38,7 +36,6 @@ LOCAL_SRC_FILES :=\
|
||||
ext/jpge/jpgd.cpp \
|
||||
ext/jpge/jpge.cpp \
|
||||
ext/sha1/sha1.cpp \
|
||||
ext/stb_vorbis/stb_vorbis.c.arm \
|
||||
ext/vjson/json.cpp \
|
||||
ext/vjson/block_allocator.cpp \
|
||||
file/fd_util.cpp \
|
||||
|
@ -1,50 +0,0 @@
|
||||
native
|
||||
======
|
||||
|
||||
This is my library of stuff that I use when writing C++ programs, mostly for Android but it's all written to enable easy portability between Android, Linux, Windows and MacOSX. The code is part ugly, part inconsistent but quite useful.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* JSON read/write (two libraries that should be made more similar)
|
||||
* basic OpenGL utility code, like compressed texture loading
|
||||
* 2D texture atlases and drawing code
|
||||
* ETC1 texture save/load support
|
||||
* basic logging
|
||||
* Really simple audio mixer with OGG sample support
|
||||
* RIFF file read/write
|
||||
* MIDI Input (only on Windows)
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
* The associated tools to create ZIM texture files and atlases do not yet live here but I might move them here eventually.
|
||||
* This library is not really meant to be a public library but I see no reason not to set it free.
|
||||
* Note that the included VS project is probably not very useful for you and you're likely better off making your own.
|
||||
* Don't complain about inconsistent naming etc - this consists of code that has been cobbled together from a variety of my projects through the years. Fashions come and go.
|
||||
|
||||
Licenses
|
||||
--------
|
||||
|
||||
This library, for my convenience, incorporates code from a variety of public domain or similarly-licensed code. This is the list:
|
||||
|
||||
* glew (GL extension wrangler), MIT license. TODO: should just use a submodule.
|
||||
* rg_etc1. ZLIB license.
|
||||
* sha1, public domain implementation by Dominik Reichl
|
||||
* vjson in a heavily modified form, originally by Ivan Vashchaev (TODO: break out into its own repo?)
|
||||
* libzip with attribution "Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner"
|
||||
* stb_vorbis, public domain by Sean Barrett of RAD Tools
|
||||
|
||||
If you're not okay with the licenses above, don't use this code.
|
||||
|
||||
I hereby release all code here not under the licenses above under the MIT license.
|
||||
|
||||
Contact
|
||||
-------
|
||||
|
||||
If you find this useful for your own projects, drop me a line at hrydgard@gmail.com .
|
||||
|
||||
Henrik Rydgård
|
||||
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
set(SRCS
|
||||
mixer.cpp
|
||||
wav_read.cpp)
|
||||
|
||||
set(SRCS ${SRCS})
|
||||
|
||||
add_library(mixer STATIC ${SRCS})
|
||||
|
||||
if(UNIX)
|
||||
add_definitions(-fPIC)
|
||||
endif(UNIX)
|
@ -1,201 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "audio/mixer.h"
|
||||
#include "audio/wav_read.h"
|
||||
#include "base/logging.h"
|
||||
#include "ext/stb_vorbis/stb_vorbis.h"
|
||||
#include "file/vfs.h"
|
||||
|
||||
// TODO:
|
||||
// * Vorbis streaming playback
|
||||
|
||||
struct ChannelEffectState {
|
||||
// Filter state
|
||||
};
|
||||
|
||||
enum CLIP_TYPE {
|
||||
CT_PCM16,
|
||||
CT_SYNTHFX,
|
||||
CT_VORBIS,
|
||||
// CT_PHOENIX?
|
||||
};
|
||||
|
||||
struct Clip {
|
||||
int type;
|
||||
|
||||
short *data;
|
||||
int length;
|
||||
int num_channels; // this is NOT stereo vs mono
|
||||
int sample_rate;
|
||||
int loop_start;
|
||||
int loop_end;
|
||||
};
|
||||
|
||||
// If current_clip == 0, the channel is free.
|
||||
|
||||
enum ClipPlaybackState {
|
||||
PB_STOPPED = 0,
|
||||
PB_PLAYING = 1,
|
||||
};
|
||||
|
||||
|
||||
struct Channel {
|
||||
const Clip *current_clip;
|
||||
// Playback state
|
||||
ClipPlaybackState state;
|
||||
int pos;
|
||||
PlayParams params;
|
||||
// Effect state
|
||||
ChannelEffectState effect_state;
|
||||
};
|
||||
|
||||
struct Mixer {
|
||||
Channel *channels;
|
||||
int sample_rate;
|
||||
int num_channels;
|
||||
int num_fixed_channels;
|
||||
};
|
||||
|
||||
Mixer *mixer_create(int sample_rate, int channels, int fixed_channels) {
|
||||
Mixer *mixer = new Mixer();
|
||||
memset(mixer, 0, sizeof(Mixer));
|
||||
mixer->channels = new Channel[channels];
|
||||
memset(mixer->channels, 0, sizeof(Channel) * channels);
|
||||
mixer->sample_rate = sample_rate;
|
||||
mixer->num_channels = channels;
|
||||
mixer->num_fixed_channels = fixed_channels;
|
||||
return mixer;
|
||||
}
|
||||
|
||||
void mixer_destroy(Mixer *mixer) {
|
||||
delete [] mixer->channels;
|
||||
delete mixer;
|
||||
}
|
||||
|
||||
static int get_free_channel(Mixer *mixer) {
|
||||
int chan_with_biggest_pos = -1;
|
||||
int biggest_pos = -1;
|
||||
for (int i = mixer->num_fixed_channels; i < mixer->num_channels; i++) {
|
||||
Channel *chan = &mixer->channels[i];
|
||||
if (!chan->current_clip) {
|
||||
return i;
|
||||
}
|
||||
if (chan->pos > biggest_pos) {
|
||||
biggest_pos = chan->pos;
|
||||
chan_with_biggest_pos = i;
|
||||
}
|
||||
}
|
||||
return chan_with_biggest_pos;
|
||||
}
|
||||
|
||||
Clip *clip_load(const char *filename) {
|
||||
short *data;
|
||||
int num_samples;
|
||||
int sample_rate, num_channels;
|
||||
|
||||
if (!strcmp(filename + strlen(filename) - 4, ".ogg")) {
|
||||
// Ogg file. For now, directly decompress, no streaming support.
|
||||
uint8_t *filedata;
|
||||
size_t size;
|
||||
filedata = VFSReadFile(filename, &size);
|
||||
num_samples = (int)stb_vorbis_decode_memory(filedata, (int)size, &num_channels, &data);
|
||||
if (num_samples <= 0)
|
||||
return NULL;
|
||||
sample_rate = 44100;
|
||||
ILOG("read ogg %s, length %i, rate %i", filename, num_samples, sample_rate);
|
||||
} else {
|
||||
// Wav file. Easy peasy.
|
||||
data = wav_read(filename, &num_samples, &sample_rate, &num_channels);
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Clip *clip = new Clip();
|
||||
clip->type = CT_PCM16;
|
||||
clip->data = data;
|
||||
clip->length = num_samples;
|
||||
clip->num_channels = num_channels;
|
||||
clip->sample_rate = sample_rate;
|
||||
clip->loop_start = 0;
|
||||
clip->loop_end = 0;
|
||||
return clip;
|
||||
}
|
||||
|
||||
void clip_destroy(Clip *clip) {
|
||||
if (clip) {
|
||||
free(clip->data);
|
||||
delete clip;
|
||||
} else {
|
||||
ELOG("Can't destroy zero clip");
|
||||
}
|
||||
}
|
||||
|
||||
const short *clip_data(const Clip *clip)
|
||||
{
|
||||
return clip->data;
|
||||
}
|
||||
|
||||
size_t clip_length(const Clip *clip) {
|
||||
return clip->length;
|
||||
}
|
||||
|
||||
void clip_set_loop(Clip *clip, int start, int end) {
|
||||
clip->loop_start = start;
|
||||
clip->loop_end = end;
|
||||
}
|
||||
|
||||
PlayParams *mixer_play_clip(Mixer *mixer, const Clip *clip, int channel) {
|
||||
if (channel == -1) {
|
||||
channel = get_free_channel(mixer);
|
||||
}
|
||||
|
||||
Channel *chan = &mixer->channels[channel];
|
||||
// Think about this order and make sure it's thread"safe" (not perfect but should not cause crashes).
|
||||
chan->pos = 0;
|
||||
chan->current_clip = clip;
|
||||
chan->state = PB_PLAYING;
|
||||
PlayParams *params = &chan->params;
|
||||
params->volume = 128;
|
||||
params->pan = 128;
|
||||
return params;
|
||||
}
|
||||
|
||||
void mixer_mix(Mixer *mixer, short *buffer, int num_samples) {
|
||||
// Clear the buffer.
|
||||
memset(buffer, 0, num_samples * sizeof(short) * 2);
|
||||
for (int i = 0; i < mixer->num_channels; i++) {
|
||||
Channel *chan = &mixer->channels[i];
|
||||
if (chan->state == PB_PLAYING) {
|
||||
const Clip *clip = chan->current_clip;
|
||||
if (clip->type == CT_PCM16) {
|
||||
// For now, only allow mono PCM
|
||||
CHECK(clip->num_channels == 1);
|
||||
if (true || chan->params.delta == 0) {
|
||||
// Fast playback of non pitched clips
|
||||
int cnt = num_samples;
|
||||
if (clip->length - chan->pos < cnt) {
|
||||
cnt = clip->length - chan->pos;
|
||||
}
|
||||
// TODO: Take pan into account.
|
||||
int left_volume = chan->params.volume;
|
||||
int right_volume = chan->params.volume;
|
||||
// TODO: NEONize. Can also make special loops for left_volume == right_volume etc.
|
||||
for (int s = 0; s < cnt; s++) {
|
||||
int cdata = clip->data[chan->pos];
|
||||
buffer[s * 2 + 0] += cdata * left_volume >> 8;
|
||||
buffer[s * 2 + 1] += cdata * right_volume >> 8;
|
||||
chan->pos++;
|
||||
}
|
||||
if (chan->pos >= clip->length) {
|
||||
chan->state = PB_STOPPED;
|
||||
chan->current_clip = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (clip->type == CT_VORBIS) {
|
||||
// For music
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
// Simple mixer intended for sound effects for games.
|
||||
// The clip loading code supports ogg SFX.
|
||||
|
||||
struct Mixer;
|
||||
struct Clip;
|
||||
struct Channel;
|
||||
|
||||
// This struct is public for easy manipulation of running channels.
|
||||
struct PlayParams {
|
||||
uint8_t volume; // 0-255
|
||||
uint8_t pan; // 0-255, 127 is dead center.
|
||||
int32_t delta;
|
||||
};
|
||||
|
||||
// Mixer
|
||||
// ==========================
|
||||
// For now, channels is required to be 2 (it specifies L/R, not mixing channels)
|
||||
Mixer *mixer_create(int sample_rate, int channels, int fixed_channels);
|
||||
void mixer_destroy(Mixer *mixer);
|
||||
|
||||
// Buffer must be r/w.
|
||||
void mixer_mix(Mixer *mixer, short *buffer, int num_samples);
|
||||
|
||||
|
||||
// Clip
|
||||
// ==========================
|
||||
Clip *clip_load(const char *filename);
|
||||
void clip_destroy(Clip *clip);
|
||||
|
||||
const short *clip_data(const Clip *clip);
|
||||
size_t clip_length(const Clip *clip);
|
||||
void clip_set_loop(int start, int end);
|
||||
|
||||
|
||||
// The returned PlayState pointer can be used to set the playback parameters,
|
||||
// but must not be kept around unless you are using a fixed channel.
|
||||
// Channel must be either -1 for auto assignment to a free channel, or less
|
||||
// than the number of fixed channels that the mixer was created with.
|
||||
PlayParams *mixer_play_clip(Mixer *mixer, const Clip *clip, int channel);
|
@ -1,70 +0,0 @@
|
||||
#include "base/basictypes.h"
|
||||
#include "base/logging.h"
|
||||
#include "audio/wav_read.h"
|
||||
#include "file/chunk_file.h"
|
||||
|
||||
short *wav_read(const char *filename,
|
||||
int *num_samples, int *sample_rate,
|
||||
int *num_channels)
|
||||
{
|
||||
ChunkFile cf(filename, true);
|
||||
if (cf.failed()) {
|
||||
WLOG("ERROR: Wave file %s could not be opened", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
short *data = 0;
|
||||
int samplesPerSec, avgBytesPerSec,wBlockAlign,wBytesPerSample;
|
||||
if (cf.descend('RIFF')) {
|
||||
cf.readInt(); //get past 'WAVE'
|
||||
if (cf.descend('fmt ')) { //enter the format chunk
|
||||
int temp = cf.readInt();
|
||||
int format = temp & 0xFFFF;
|
||||
if (format != 1) {
|
||||
cf.ascend();
|
||||
cf.ascend();
|
||||
ELOG("Error - bad format");
|
||||
return NULL;
|
||||
}
|
||||
*num_channels = temp >> 16;
|
||||
samplesPerSec = cf.readInt();
|
||||
avgBytesPerSec = cf.readInt();
|
||||
|
||||
temp = cf.readInt();
|
||||
wBlockAlign = temp & 0xFFFF;
|
||||
wBytesPerSample = temp >> 16;
|
||||
cf.ascend();
|
||||
// ILOG("got fmt data: %i", samplesPerSec);
|
||||
} else {
|
||||
ELOG("Error - no format chunk in wav");
|
||||
cf.ascend();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cf.descend('data')) { //enter the data chunk
|
||||
int numBytes = cf.getCurrentChunkSize();
|
||||
int numSamples = numBytes / wBlockAlign;
|
||||
data = (short *)malloc(sizeof(short) * numSamples * *num_channels);
|
||||
*num_samples = numSamples;
|
||||
if (wBlockAlign == 2 && *num_channels == 1) {
|
||||
cf.readData((uint8_t *)data,numBytes);
|
||||
} else {
|
||||
ELOG("Error - bad blockalign or channels");
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
cf.ascend();
|
||||
} else {
|
||||
ELOG("Error - no data chunk in wav");
|
||||
cf.ascend();
|
||||
return NULL;
|
||||
}
|
||||
cf.ascend();
|
||||
} else {
|
||||
ELOG("Could not descend into RIFF file");
|
||||
return NULL;
|
||||
}
|
||||
*sample_rate = samplesPerSec;
|
||||
ILOG("read wav %s, length %i, rate %i", filename, *num_samples, *sample_rate);
|
||||
return data;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#include "base/basictypes.h"
|
||||
|
||||
// Allocates a buffer that should be freed using free().
|
||||
short *wav_read(const char *filename,
|
||||
int *num_samples, int *sample_rate,
|
||||
int *num_channels);
|
||||
// TODO: Non-allocating version.
|
@ -1,10 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
#if(UNIX)
|
||||
add_definitions(-fPIC)
|
||||
add_definitions(-g)
|
||||
add_definitions(-O2)
|
||||
add_definitions(-Wall)
|
||||
#endif(UNIX)
|
||||
|
||||
add_library(stb_vorbis stb_vorbis.c)
|
File diff suppressed because it is too large
Load Diff
@ -1,329 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// HEADER BEGINS HERE
|
||||
//
|
||||
|
||||
#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||
#define STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||
|
||||
#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)
|
||||
#define STB_VORBIS_NO_STDIO 1
|
||||
#endif
|
||||
|
||||
#ifndef STB_VORBIS_NO_STDIO
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/////////// THREAD SAFETY
|
||||
|
||||
// Individual stb_vorbis* handles are not thread-safe; you cannot decode from
|
||||
// them from multiple threads at the same time. However, you can have multiple
|
||||
// stb_vorbis* handles and decode from them independently in multiple thrads.
|
||||
|
||||
|
||||
/////////// MEMORY ALLOCATION
|
||||
|
||||
// normally stb_vorbis uses malloc() to allocate memory at startup,
|
||||
// and alloca() to allocate temporary memory during a frame on the
|
||||
// stack. (Memory consumption will depend on the amount of setup
|
||||
// data in the file and how you set the compile flags for speed
|
||||
// vs. size. In my test files the maximal-size usage is ~150KB.)
|
||||
//
|
||||
// You can modify the wrapper functions in the source (setup_malloc,
|
||||
// setup_temp_malloc, temp_malloc) to change this behavior, or you
|
||||
// can use a simpler allocation model: you pass in a buffer from
|
||||
// which stb_vorbis will allocate _all_ its memory (including the
|
||||
// temp memory). "open" may fail with a VORBIS_outofmem if you
|
||||
// do not pass in enough data; there is no way to determine how
|
||||
// much you do need except to succeed (at which point you can
|
||||
// query get_info to find the exact amount required. yes I know
|
||||
// this is lame).
|
||||
//
|
||||
// If you pass in a non-NULL buffer of the type below, allocation
|
||||
// will occur from it as described above. Otherwise just pass NULL
|
||||
// to use malloc()/alloca()
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *alloc_buffer;
|
||||
int alloc_buffer_length_in_bytes;
|
||||
} stb_vorbis_alloc;
|
||||
|
||||
|
||||
/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES
|
||||
|
||||
typedef struct stb_vorbis stb_vorbis;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int sample_rate;
|
||||
int channels;
|
||||
|
||||
unsigned int setup_memory_required;
|
||||
unsigned int setup_temp_memory_required;
|
||||
unsigned int temp_memory_required;
|
||||
|
||||
int max_frame_size;
|
||||
} stb_vorbis_info;
|
||||
|
||||
// get general information about the file
|
||||
extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f);
|
||||
|
||||
// get the last error detected (clears it, too)
|
||||
extern int stb_vorbis_get_error(stb_vorbis *f);
|
||||
|
||||
// close an ogg vorbis file and free all memory in use
|
||||
extern void stb_vorbis_close(stb_vorbis *f);
|
||||
|
||||
// this function returns the offset (in samples) from the beginning of the
|
||||
// file that will be returned by the next decode, if it is known, or -1
|
||||
// otherwise. after a flush_pushdata() call, this may take a while before
|
||||
// it becomes valid again.
|
||||
// NOT WORKING YET after a seek with PULLDATA API
|
||||
extern int stb_vorbis_get_sample_offset(stb_vorbis *f);
|
||||
|
||||
// returns the current seek point within the file, or offset from the beginning
|
||||
// of the memory buffer. In pushdata mode it returns 0.
|
||||
extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f);
|
||||
|
||||
/////////// PUSHDATA API
|
||||
|
||||
#ifndef STB_VORBIS_NO_PUSHDATA_API
|
||||
|
||||
// this API allows you to get blocks of data from any source and hand
|
||||
// them to stb_vorbis. you have to buffer them; stb_vorbis will tell
|
||||
// you how much it used, and you have to give it the rest next time;
|
||||
// and stb_vorbis may not have enough data to work with and you will
|
||||
// need to give it the same data again PLUS more. Note that the Vorbis
|
||||
// specification does not bound the size of an individual frame.
|
||||
|
||||
extern stb_vorbis *stb_vorbis_open_pushdata(
|
||||
unsigned char *datablock, int datablock_length_in_bytes,
|
||||
int *datablock_memory_consumed_in_bytes,
|
||||
int *error,
|
||||
stb_vorbis_alloc *alloc_buffer);
|
||||
// create a vorbis decoder by passing in the initial data block containing
|
||||
// the ogg&vorbis headers (you don't need to do parse them, just provide
|
||||
// the first N bytes of the file--you're told if it's not enough, see below)
|
||||
// on success, returns an stb_vorbis *, does not set error, returns the amount of
|
||||
// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes;
|
||||
// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed
|
||||
// if returns NULL and *error is VORBIS_need_more_data, then the input block was
|
||||
// incomplete and you need to pass in a larger block from the start of the file
|
||||
|
||||
extern int stb_vorbis_decode_frame_pushdata(
|
||||
stb_vorbis *f, unsigned char *datablock, int datablock_length_in_bytes,
|
||||
int *channels, // place to write number of float * buffers
|
||||
float ***output, // place to write float ** array of float * buffers
|
||||
int *samples // place to write number of output samples
|
||||
);
|
||||
// decode a frame of audio sample data if possible from the passed-in data block
|
||||
//
|
||||
// return value: number of bytes we used from datablock
|
||||
// possible cases:
|
||||
// 0 bytes used, 0 samples output (need more data)
|
||||
// N bytes used, 0 samples output (resynching the stream, keep going)
|
||||
// N bytes used, M samples output (one frame of data)
|
||||
// note that after opening a file, you will ALWAYS get one N-bytes,0-sample
|
||||
// frame, because Vorbis always "discards" the first frame.
|
||||
//
|
||||
// Note that on resynch, stb_vorbis will rarely consume all of the buffer,
|
||||
// instead only datablock_length_in_bytes-3 or less. This is because it wants
|
||||
// to avoid missing parts of a page header if they cross a datablock boundary,
|
||||
// without writing state-machiney code to record a partial detection.
|
||||
//
|
||||
// The number of channels returned are stored in *channels (which can be
|
||||
// NULL--it is always the same as the number of channels reported by
|
||||
// get_info). *output will contain an array of float* buffers, one per
|
||||
// channel. In other words, (*output)[0][0] contains the first sample from
|
||||
// the first channel, and (*output)[1][0] contains the first sample from
|
||||
// the second channel.
|
||||
|
||||
extern void stb_vorbis_flush_pushdata(stb_vorbis *f);
|
||||
// inform stb_vorbis that your next datablock will not be contiguous with
|
||||
// previous ones (e.g. you've seeked in the data); future attempts to decode
|
||||
// frames will cause stb_vorbis to resynchronize (as noted above), and
|
||||
// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it
|
||||
// will begin decoding the _next_ frame.
|
||||
//
|
||||
// if you want to seek using pushdata, you need to seek in your file, then
|
||||
// call stb_vorbis_flush_pushdata(), then start calling decoding, then once
|
||||
// decoding is returning you data, call stb_vorbis_get_sample_offset, and
|
||||
// if you don't like the result, seek your file again and repeat.
|
||||
#endif
|
||||
|
||||
|
||||
////////// PULLING INPUT API
|
||||
|
||||
#ifndef STB_VORBIS_NO_PULLDATA_API
|
||||
// This API assumes stb_vorbis is allowed to pull data from a source--
|
||||
// either a block of memory containing the _entire_ vorbis stream, or a
|
||||
// FILE * that you or it create, or possibly some other reading mechanism
|
||||
// if you go modify the source to replace the FILE * case with some kind
|
||||
// of callback to your code. (But if you don't support seeking, you may
|
||||
// just want to go ahead and use pushdata.)
|
||||
|
||||
#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION)
|
||||
extern int stb_vorbis_decode_filename(char *filename, int *channels, short **output);
|
||||
#endif
|
||||
extern int stb_vorbis_decode_memory(unsigned char *mem, int len, int *channels, short **output);
|
||||
// decode an entire file and output the data interleaved into a malloc()ed
|
||||
// buffer stored in *output. The return value is the number of samples
|
||||
// decoded, or -1 if the file could not be opened or was not an ogg vorbis file.
|
||||
// When you're done with it, just free() the pointer returned in *output.
|
||||
|
||||
extern stb_vorbis * stb_vorbis_open_memory(unsigned char *data, int len,
|
||||
int *error, stb_vorbis_alloc *alloc_buffer);
|
||||
// create an ogg vorbis decoder from an ogg vorbis stream in memory (note
|
||||
// this must be the entire stream!). on failure, returns NULL and sets *error
|
||||
|
||||
#ifndef STB_VORBIS_NO_STDIO
|
||||
extern stb_vorbis * stb_vorbis_open_filename(char *filename,
|
||||
int *error, stb_vorbis_alloc *alloc_buffer);
|
||||
// create an ogg vorbis decoder from a filename via fopen(). on failure,
|
||||
// returns NULL and sets *error (possibly to VORBIS_file_open_failure).
|
||||
|
||||
extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
|
||||
int *error, stb_vorbis_alloc *alloc_buffer);
|
||||
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
||||
// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
|
||||
// note that stb_vorbis must "own" this stream; if you seek it in between
|
||||
// calls to stb_vorbis, it will become confused. Morever, if you attempt to
|
||||
// perform stb_vorbis_seek_*() operations on this file, it will assume it
|
||||
// owns the _entire_ rest of the file after the start point. Use the next
|
||||
// function, stb_vorbis_open_file_section(), to limit it.
|
||||
|
||||
extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,
|
||||
int *error, stb_vorbis_alloc *alloc_buffer, unsigned int len);
|
||||
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
||||
// the _current_ seek point (ftell); the stream will be of length 'len' bytes.
|
||||
// on failure, returns NULL and sets *error. note that stb_vorbis must "own"
|
||||
// this stream; if you seek it in between calls to stb_vorbis, it will become
|
||||
// confused.
|
||||
#endif
|
||||
|
||||
extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number);
|
||||
extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
|
||||
// NOT WORKING YET
|
||||
// these functions seek in the Vorbis file to (approximately) 'sample_number'.
|
||||
// after calling seek_frame(), the next call to get_frame_*() will include
|
||||
// the specified sample. after calling stb_vorbis_seek(), the next call to
|
||||
// stb_vorbis_get_samples_* will start with the specified sample. If you
|
||||
// do not need to seek to EXACTLY the target sample when using get_samples_*,
|
||||
// you can also use seek_frame().
|
||||
|
||||
extern void stb_vorbis_seek_start(stb_vorbis *f);
|
||||
// this function is equivalent to stb_vorbis_seek(f,0), but it
|
||||
// actually works
|
||||
|
||||
extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f);
|
||||
extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f);
|
||||
// these functions return the total length of the vorbis stream
|
||||
|
||||
extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output);
|
||||
// decode the next frame and return the number of samples. the number of
|
||||
// channels returned are stored in *channels (which can be NULL--it is always
|
||||
// the same as the number of channels reported by get_info). *output will
|
||||
// contain an array of float* buffers, one per channel. These outputs will
|
||||
// be overwritten on the next call to stb_vorbis_get_frame_*.
|
||||
//
|
||||
// You generally should not intermix calls to stb_vorbis_get_frame_*()
|
||||
// and stb_vorbis_get_samples_*(), since the latter calls the former.
|
||||
|
||||
#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
|
||||
extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);
|
||||
extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples);
|
||||
#endif
|
||||
// decode the next frame and return the number of samples per channel. the
|
||||
// data is coerced to the number of channels you request according to the
|
||||
// channel coercion rules (see below). You must pass in the size of your
|
||||
// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
|
||||
// The maximum buffer size needed can be gotten from get_info(); however,
|
||||
// the Vorbis I specification implies an absolute maximum of 4096 samples
|
||||
// per channel. Note that for interleaved data, you pass in the number of
|
||||
// shorts (the size of your array), but the return value is the number of
|
||||
// samples per channel, not the total number of samples.
|
||||
|
||||
// Channel coercion rules:
|
||||
// Let M be the number of channels requested, and N the number of channels present,
|
||||
// and Cn be the nth channel; let stereo L be the sum of all L and center channels,
|
||||
// and stereo R be the sum of all R and center channels (channel assignment from the
|
||||
// vorbis spec).
|
||||
// M N output
|
||||
// 1 k sum(Ck) for all k
|
||||
// 2 * stereo L, stereo R
|
||||
// k l k > l, the first l channels, then 0s
|
||||
// k l k <= l, the first k channels
|
||||
// Note that this is not _good_ surround etc. mixing at all! It's just so
|
||||
// you get something useful.
|
||||
|
||||
extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats);
|
||||
extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples);
|
||||
// gets num_samples samples, not necessarily on a frame boundary--this requires
|
||||
// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES.
|
||||
// Returns the number of samples stored per channel; it may be less than requested
|
||||
// at the end of the file. If there are no more samples in the file, returns 0.
|
||||
|
||||
#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
|
||||
extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts);
|
||||
extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples);
|
||||
#endif
|
||||
// gets num_samples samples, not necessarily on a frame boundary--this requires
|
||||
// buffering so you have to supply the buffers. Applies the coercion rules above
|
||||
// to produce 'channels' channels. Returns the number of samples stored per channel;
|
||||
// it may be less than requested at the end of the file. If there are no more
|
||||
// samples in the file, returns 0.
|
||||
|
||||
#endif
|
||||
|
||||
//////// ERROR CODES
|
||||
|
||||
enum STBVorbisError
|
||||
{
|
||||
VORBIS__no_error,
|
||||
|
||||
VORBIS_need_more_data=1, // not a real error
|
||||
|
||||
VORBIS_invalid_api_mixing, // can't mix API modes
|
||||
VORBIS_outofmem, // not enough memory
|
||||
VORBIS_feature_not_supported, // uses floor 0
|
||||
VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small
|
||||
VORBIS_file_open_failure, // fopen() failed
|
||||
VORBIS_seek_without_length, // can't seek in unknown-length file
|
||||
|
||||
VORBIS_unexpected_eof=10, // file is truncated?
|
||||
VORBIS_seek_invalid, // seek past EOF
|
||||
|
||||
// decoding errors (corrupt/invalid stream) -- you probably
|
||||
// don't care about the exact details of these
|
||||
|
||||
// vorbis errors:
|
||||
VORBIS_invalid_setup=20,
|
||||
VORBIS_invalid_stream,
|
||||
|
||||
// ogg errors:
|
||||
VORBIS_missing_capture_pattern=30,
|
||||
VORBIS_invalid_stream_structure_version,
|
||||
VORBIS_continued_packet_flag_invalid,
|
||||
VORBIS_incorrect_stream_serial_number,
|
||||
VORBIS_invalid_first_page,
|
||||
VORBIS_bad_packet_type,
|
||||
VORBIS_cant_find_last_page,
|
||||
VORBIS_seek_failed,
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||
//
|
||||
// HEADER ENDS HERE
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -187,8 +187,6 @@
|
||||
<None Include="math\fast\fast_matrix_neon.S" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="audio\mixer.h" />
|
||||
<ClInclude Include="audio\wav_read.h" />
|
||||
<ClInclude Include="base\backtrace.h" />
|
||||
<ClInclude Include="base\basictypes.h" />
|
||||
<ClInclude Include="base\buffer.h" />
|
||||
@ -220,7 +218,6 @@
|
||||
<ClInclude Include="ext\libzip\zipint.h" />
|
||||
<ClInclude Include="ext\rg_etc1\rg_etc1.h" />
|
||||
<ClInclude Include="ext\sha1\sha1.h" />
|
||||
<ClInclude Include="ext\stb_vorbis\stb_vorbis.h" />
|
||||
<ClInclude Include="ext\vjson\block_allocator.h" />
|
||||
<ClInclude Include="ext\vjson\json.h" />
|
||||
<ClInclude Include="file\chunk_file.h" />
|
||||
@ -289,8 +286,6 @@
|
||||
<ClInclude Include="util\text\utf8.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="audio\mixer.cpp" />
|
||||
<ClCompile Include="audio\wav_read.cpp" />
|
||||
<ClCompile Include="base\backtrace.cpp" />
|
||||
<ClCompile Include="base\BlackberryMain.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
@ -683,7 +678,6 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="ext\rg_etc1\rg_etc1.cpp" />
|
||||
<ClCompile Include="ext\sha1\sha1.cpp" />
|
||||
<ClCompile Include="ext\stb_vorbis\stb_vorbis.c" />
|
||||
<ClCompile Include="ext\vjson\block_allocator.cpp" />
|
||||
<ClCompile Include="ext\vjson\json.cpp" />
|
||||
<ClCompile Include="file\chunk_file.cpp" />
|
||||
|
@ -57,12 +57,6 @@
|
||||
<ClInclude Include="gfx_es2\glsl_program.h">
|
||||
<Filter>gfx</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="audio\wav_read.h">
|
||||
<Filter>audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="audio\mixer.h">
|
||||
<Filter>audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="profiler\profiler.h">
|
||||
<Filter>profiler</Filter>
|
||||
</ClInclude>
|
||||
@ -183,9 +177,6 @@
|
||||
<ClInclude Include="ui\ui_context.h">
|
||||
<Filter>ui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ext\stb_vorbis\stb_vorbis.h">
|
||||
<Filter>ext</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gfx_es2\gpu_features.h">
|
||||
<Filter>gfx</Filter>
|
||||
</ClInclude>
|
||||
@ -359,12 +350,6 @@
|
||||
<ClCompile Include="gfx_es2\glsl_program.cpp">
|
||||
<Filter>gfx</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="audio\wav_read.cpp">
|
||||
<Filter>audio</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="audio\mixer.cpp">
|
||||
<Filter>audio</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="profiler\profiler.cpp">
|
||||
<Filter>profiler</Filter>
|
||||
</ClCompile>
|
||||
@ -460,9 +445,6 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="base\BlackberryMain.cpp" />
|
||||
<ClCompile Include="base\PCMain.cpp" />
|
||||
<ClCompile Include="ext\stb_vorbis\stb_vorbis.c">
|
||||
<Filter>ext</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="base\BlackberryMain.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
|
Loading…
Reference in New Issue
Block a user