Add basic sound support

This commit is contained in:
Liriosha 2026-03-18 19:47:05 -04:00
parent 956dfd369c
commit 456ddff37e
7 changed files with 103893 additions and 1551 deletions

File diff suppressed because it is too large Load diff

View file

@ -3,167 +3,178 @@ class Mob;
class Options; class Options;
using namespace std; using namespace std;
#include "../../Minecraft.World/Util/SoundTypes.h" #include "../../Minecraft.World/Util/SoundTypes.h"
#include "./miniaudio.h"
enum eMUSICFILES constexpr float SFX_3D_MIN_DISTANCE = 1.0f;
{ constexpr float SFX_3D_MAX_DISTANCE = 16.0f;
eStream_Overworld_Calm1 = 0, constexpr float SFX_3D_ROLLOFF = 0.5f;
eStream_Overworld_Calm2, constexpr float SFX_VOLUME_MULTIPLIER = 1.5f;
eStream_Overworld_Calm3, constexpr float SFX_MAX_GAIN = 1.5f;
eStream_Overworld_hal1, enum eMUSICFILES {
eStream_Overworld_hal2, eStream_Overworld_Calm1 = 0,
eStream_Overworld_hal3, eStream_Overworld_Calm2,
eStream_Overworld_hal4, eStream_Overworld_Calm3,
eStream_Overworld_nuance1, eStream_Overworld_hal1,
eStream_Overworld_nuance2, eStream_Overworld_hal2,
eStream_Overworld_hal3,
eStream_Overworld_hal4,
eStream_Overworld_nuance1,
eStream_Overworld_nuance2,
#ifndef _XBOX #ifndef _XBOX
// Add the new music tracks // Add the new music tracks
eStream_Overworld_Creative1, eStream_Overworld_Creative1,
eStream_Overworld_Creative2, eStream_Overworld_Creative2,
eStream_Overworld_Creative3, eStream_Overworld_Creative3,
eStream_Overworld_Creative4, eStream_Overworld_Creative4,
eStream_Overworld_Creative5, eStream_Overworld_Creative5,
eStream_Overworld_Creative6, eStream_Overworld_Creative6,
eStream_Overworld_Menu1, eStream_Overworld_Menu1,
eStream_Overworld_Menu2, eStream_Overworld_Menu2,
eStream_Overworld_Menu3, eStream_Overworld_Menu3,
eStream_Overworld_Menu4, eStream_Overworld_Menu4,
#endif #endif
eStream_Overworld_piano1, eStream_Overworld_piano1,
eStream_Overworld_piano2, eStream_Overworld_piano2,
eStream_Overworld_piano3, // <-- make piano3 the last overworld one eStream_Overworld_piano3, // <-- make piano3 the last overworld one
// Nether // Nether
eStream_Nether1, eStream_Nether1,
eStream_Nether2, eStream_Nether2,
eStream_Nether3, eStream_Nether3,
eStream_Nether4, eStream_Nether4,
// The End // The End
eStream_end_dragon, eStream_end_dragon,
eStream_end_end, eStream_end_end,
eStream_CD_1, eStream_CD_1,
eStream_CD_2, eStream_CD_2,
eStream_CD_3, eStream_CD_3,
eStream_CD_4, eStream_CD_4,
eStream_CD_5, eStream_CD_5,
eStream_CD_6, eStream_CD_6,
eStream_CD_7, eStream_CD_7,
eStream_CD_8, eStream_CD_8,
eStream_CD_9, eStream_CD_9,
eStream_CD_10, eStream_CD_10,
eStream_CD_11, eStream_CD_11,
eStream_CD_12, eStream_CD_12,
eStream_Max, eStream_Max,
}; };
enum eMUSICTYPE enum eMUSICTYPE {
{ eMusicType_None,
eMusicType_None, eMusicType_Game,
eMusicType_Game, eMusicType_CD,
eMusicType_CD,
}; };
enum MUSIC_STREAMSTATE {
enum MUSIC_STREAMSTATE eMusicStreamState_Idle = 0,
{ eMusicStreamState_Stop,
eMusicStreamState_Idle=0, eMusicStreamState_Stopping,
eMusicStreamState_Stop, eMusicStreamState_Opening,
eMusicStreamState_Stopping, eMusicStreamState_OpeningCancel,
eMusicStreamState_Opening, eMusicStreamState_Play,
eMusicStreamState_OpeningCancel, eMusicStreamState_Playing,
eMusicStreamState_Play, eMusicStreamState_Completed
eMusicStreamState_Playing,
eMusicStreamState_Completed
}; };
typedef struct typedef struct {
{ F32 x, y, z, volume, pitch;
F32 x,y,z,volume,pitch; int iSound;
int iSound; bool bIs3D;
bool bIs3D; bool bUseSoundsPitchVal;
bool bUseSoundsPitchVal;
#ifdef _DEBUG #ifdef _DEBUG
char chName[64]; char chName[64];
#endif #endif
} } AUDIO_INFO;
AUDIO_INFO; struct MiniAudioSound {
ma_sound sound;
class SoundEngine : public ConsoleSoundEngine AUDIO_INFO info;
{ bool active;
static const int MAX_SAME_SOUNDS_PLAYING = 8; // 4J added };
class SoundEngine : public ConsoleSoundEngine {
static const int MAX_SAME_SOUNDS_PLAYING = 8; // 4J added
public: public:
SoundEngine(); SoundEngine();
virtual void destroy(); virtual void destroy();
#ifdef _DEBUG #ifdef _DEBUG
void GetSoundName(char *szSoundName,int iSound); void GetSoundName(char* szSoundName, int iSound);
#endif #endif
virtual void play(int iSound, float x, float y, float z, float volume, float pitch); virtual void play(int iSound, float x, float y, float z, float volume,
virtual void playStreaming(const std::wstring& name, float x, float y , float z, float volume, float pitch, bool bMusicDelay=true); float pitch);
virtual void playUI(int iSound, float volume, float pitch); virtual void playStreaming(const std::wstring& name, float x, float y,
virtual void playMusicTick(); float z, float volume, float pitch,
virtual void updateMusicVolume(float fVal); bool bMusicDelay = true);
virtual void updateSystemMusicPlaying(bool isPlaying); virtual void playUI(int iSound, float volume, float pitch);
virtual void updateSoundEffectVolume(float fVal); virtual void playMusicTick();
virtual void init(Options *); virtual void updateMusicVolume(float fVal);
virtual void tick(std::shared_ptr<Mob> *players, float a); // 4J - updated to take array of local players rather than single one virtual void updateSystemMusicPlaying(bool isPlaying);
virtual void add(const std::wstring& name, File *file); virtual void updateSoundEffectVolume(float fVal);
virtual void addMusic(const std::wstring& name, File *file); virtual void init(Options*);
virtual void addStreaming(const std::wstring& name, File *file); virtual void tick(std::shared_ptr<Mob>* players,
virtual char *ConvertSoundPathToName(const std::wstring& name, bool bConvertSpaces=false); float a); // 4J - updated to take array of local players
bool isStreamingWavebankReady(); // 4J Added // rather than single one
int getMusicID(int iDomain); virtual void add(const std::wstring& name, File* file);
int getMusicID(const std::wstring& name); virtual void addMusic(const std::wstring& name, File* file);
void SetStreamingSounds(int iOverworldMin, int iOverWorldMax, int iNetherMin, int iNetherMax, int iEndMin, int iEndMax, int iCD1); virtual void addStreaming(const std::wstring& name, File* file);
void updateMiles(); // AP added so Vita can update all the Miles functions during the mixer callback virtual char* ConvertSoundPathToName(const std::wstring& name,
void playMusicUpdate(); bool bConvertSpaces = false);
bool isStreamingWavebankReady(); // 4J Added
int getMusicID(int iDomain);
int getMusicID(const std::wstring& name);
void SetStreamingSounds(int iOverworldMin, int iOverWorldMax,
int iNetherMin, int iNetherMax, int iEndMin,
int iEndMax, int iCD1);
void updateMiles(); // AP added so Vita can update all the Miles functions
// during the mixer callback
void playMusicUpdate();
private: private:
float getMasterMusicVolume(); float getMasterMusicVolume();
// platform specific functions // platform specific functions
#ifdef __PS3__ #ifdef __PS3__
int initAudioHardware(int iMinSpeakers); int initAudioHardware(int iMinSpeakers);
#else #else
int initAudioHardware(int iMinSpeakers) { return iMinSpeakers;} int initAudioHardware(int iMinSpeakers) { return iMinSpeakers; }
#endif #endif
int GetRandomishTrack(int iStart,int iEnd);
HMSOUNDBANK m_hBank; int GetRandomishTrack(int iStart, int iEnd);
HDIGDRIVER m_hDriver;
HSTREAM m_hStream;
static char m_szSoundPath[]; ma_engine m_engine;
static char m_szMusicPath[]; ma_engine_config m_engineConfig;
static char m_szRedistName[]; ma_sound m_musicStream;
static char *m_szStreamFileA[eStream_Max]; bool m_musicStreamActive;
AUDIO_LISTENER m_ListenerA[MAX_LOCAL_PLAYERS]; static char m_szSoundPath[];
int m_validListenerCount; static char m_szMusicPath[];
static char m_szRedistName[];
static const char* m_szStreamFileA[eStream_Max];
AUDIO_LISTENER m_ListenerA[MAX_LOCAL_PLAYERS];
int m_validListenerCount;
Random *random; Random* random;
int m_musicID; int m_musicID;
int m_iMusicDelay; int m_iMusicDelay;
int m_StreamState; int m_StreamState;
int m_MusicType; int m_MusicType;
AUDIO_INFO m_StreamingAudioInfo; AUDIO_INFO m_StreamingAudioInfo;
std::wstring m_CDMusic; std::wstring m_CDMusic;
bool m_bSystemMusicPlaying; bool m_bSystemMusicPlaying;
float m_MasterMusicVolume; float m_MasterMusicVolume;
float m_MasterEffectsVolume; float m_MasterEffectsVolume;
C4JThread *m_openStreamThread; C4JThread* m_openStreamThread;
static int OpenStreamThreadProc( void* lpParameter ); static int OpenStreamThreadProc(void* lpParameter);
char m_szStreamName[255]; char m_szStreamName[255];
int CurrentSoundsPlaying[static_cast<int>(eSoundType_MAX) + int CurrentSoundsPlaying[static_cast<int>(eSoundType_MAX) +
static_cast<int>(eSFX_MAX)]; static_cast<int>(eSFX_MAX)];
// streaming music files - will be different for mash-up packs // streaming music files - will be different for mash-up packs
int m_iStream_Overworld_Min,m_iStream_Overworld_Max; int m_iStream_Overworld_Min, m_iStream_Overworld_Max;
int m_iStream_Nether_Min,m_iStream_Nether_Max; int m_iStream_Nether_Min, m_iStream_Nether_Max;
int m_iStream_End_Min,m_iStream_End_Max; int m_iStream_End_Min, m_iStream_End_Max;
int m_iStream_CD_1; int m_iStream_CD_1;
bool *m_bHeardTrackA; bool* m_bHeardTrackA;
#ifdef __ORBIS__ #ifdef __ORBIS__
int32_t m_hBGMAudio; int32_t m_hBGMAudio;
#endif #endif
}; };

View file

@ -2,164 +2,157 @@
#include "Consoles_SoundEngine.h" #include "Consoles_SoundEngine.h"
const WCHAR* ConsoleSoundEngine::wchSoundNames[eSoundType_MAX] = {
L"mob/chicken/chicken", // eSoundType_MOB_CHICKEN_AMBIENT
const WCHAR *ConsoleSoundEngine::wchSoundNames[eSoundType_MAX]= L"mob/chicken/chickenhurt", // eSoundType_MOB_CHICKEN_HURT
{ L"mob/chicken/chickenplop", // eSoundType_MOB_CHICKENPLOP
L"mob/chicken", // eSoundType_MOB_CHICKEN_AMBIENT L"mob/cow/say", // eSoundType_MOB_COW_AMBIENT
L"mob/chickenhurt", // eSoundType_MOB_CHICKEN_HURT L"mob/cow/hurt", // eSoundType_MOB_COW_HURT
L"mob/chickenplop", // eSoundType_MOB_CHICKENPLOP L"mob/pig/say", // eSoundType_MOB_PIG_AMBIENT
L"mob/cow", // eSoundType_MOB_COW_AMBIENT L"mob/pig/pigdeath", // eSoundType_MOB_PIG_DEATH
L"mob/cowhurt", // eSoundType_MOB_COW_HURT L"mob/sheep/sheep", // eSoundType_MOB_SHEEP_AMBIENT
L"mob/pig", // eSoundType_MOB_PIG_AMBIENT L"mob/wolf/growl", // eSoundType_MOB_WOLF_GROWL
L"mob/pigdeath", // eSoundType_MOB_PIG_DEATH L"mob/wolf/whine", // eSoundType_MOB_WOLF_WHINE
L"mob/sheep", // eSoundType_MOB_SHEEP_AMBIENT L"mob/wolf/panting", // eSoundType_MOB_WOLF_PANTING
L"mob/wolf/growl", // eSoundType_MOB_WOLF_GROWL L"mob/wolf/bark", // eSoundType_MOB_WOLF_BARK
L"mob/wolf/whine", // eSoundType_MOB_WOLF_WHINE L"mob/wolf/hurt", // eSoundType_MOB_WOLF_HURT
L"mob/wolf/panting", // eSoundType_MOB_WOLF_PANTING L"mob/wolf/death", // eSoundType_MOB_WOLF_DEATH
L"mob/wolf/bark", // eSoundType_MOB_WOLF_BARK L"mob/wolf/shake", // eSoundType_MOB_WOLF_SHAKE
L"mob/wolf/hurt", // eSoundType_MOB_WOLF_HURT L"mob/blaze/breathe", // eSoundType_MOB_BLAZE_BREATHE
L"mob/wolf/death", // eSoundType_MOB_WOLF_DEATH L"mob/blaze/hit", // eSoundType_MOB_BLAZE_HURT
L"mob/wolf/shake", // eSoundType_MOB_WOLF_SHAKE L"mob/blaze/death", // eSoundType_MOB_BLAZE_DEATH
L"mob/blaze/breathe", // eSoundType_MOB_BLAZE_BREATHE L"mob/ghast/moan", // eSoundType_MOB_GHAST_MOAN
L"mob/blaze/hit", // eSoundType_MOB_BLAZE_HURT L"mob/ghast/scream", // eSoundType_MOB_GHAST_SCREAM
L"mob/blaze/death", // eSoundType_MOB_BLAZE_DEATH L"mob/ghast/death", // eSoundType_MOB_GHAST_DEATH
L"mob/ghast/moan", // eSoundType_MOB_GHAST_MOAN L"mob/ghast/fireball", // eSoundType_MOB_GHAST_FIREBALL
L"mob/ghast/scream", // eSoundType_MOB_GHAST_SCREAM L"mob/ghast/charge", // eSoundType_MOB_GHAST_CHARGE
L"mob/ghast/death", // eSoundType_MOB_GHAST_DEATH L"mob/endermen/idle", // eSoundType_MOB_ENDERMEN_IDLE
L"mob/ghast/fireball", // eSoundType_MOB_GHAST_FIREBALL L"mob/endermen/hit", // eSoundType_MOB_ENDERMEN_HIT
L"mob/ghast/charge", // eSoundType_MOB_GHAST_CHARGE L"mob/endermen/death", // eSoundType_MOB_ENDERMEN_DEATH
L"mob/endermen/idle", // eSoundType_MOB_ENDERMEN_IDLE L"mob/endermen/portal", // eSoundType_MOB_ENDERMEN_PORTAL
L"mob/endermen/hit", // eSoundType_MOB_ENDERMEN_HIT L"mob/zombiepig/zpig", // eSoundType_MOB_ZOMBIEPIG_AMBIENT
L"mob/endermen/death", // eSoundType_MOB_ENDERMEN_DEATH L"mob/zombiepig/zpighurt", // eSoundType_MOB_ZOMBIEPIG_HURT
L"mob/endermen/portal", // eSoundType_MOB_ENDERMEN_PORTAL L"mob/zombiepig/zpigdeath", // eSoundType_MOB_ZOMBIEPIG_DEATH
L"mob/zombiepig/zpig", // eSoundType_MOB_ZOMBIEPIG_AMBIENT L"mob/zombiepig/zpigangry", // eSoundType_MOB_ZOMBIEPIG_ZPIGANGRY
L"mob/zombiepig/zpighurt", // eSoundType_MOB_ZOMBIEPIG_HURT L"mob/silverfish/say", // eSoundType_MOB_SILVERFISH_AMBIENT,
L"mob/zombiepig/zpigdeath", // eSoundType_MOB_ZOMBIEPIG_DEATH L"mob/silverfish/hit", // eSoundType_MOB_SILVERFISH_HURT
L"mob/zombiepig/zpigangry", // eSoundType_MOB_ZOMBIEPIG_ZPIGANGRY L"mob/silverfish/kill", // eSoundType_MOB_SILVERFISH_DEATH,
L"mob/silverfish/say", // eSoundType_MOB_SILVERFISH_AMBIENT, L"mob/silverfish/step", // eSoundType_MOB_SILVERFISH_STEP,
L"mob/silverfish/hit", // eSoundType_MOB_SILVERFISH_HURT L"mob/skeleton/skeleton", // eSoundType_MOB_SKELETON_AMBIENT,
L"mob/silverfish/kill", // eSoundType_MOB_SILVERFISH_DEATH, L"mob/skeleton/skeletonhurt", // eSoundType_MOB_SKELETON_HURT,
L"mob/silverfish/step", // eSoundType_MOB_SILVERFISH_STEP, L"mob/spider/spider", // eSoundType_MOB_SPIDER_AMBIENT,
L"mob/skeleton", // eSoundType_MOB_SKELETON_AMBIENT, L"mob/spider/spiderdeath", // eSoundType_MOB_SPIDER_DEATH,
L"mob/skeletonhurt", // eSoundType_MOB_SKELETON_HURT, L"mob/slime/slime", // eSoundType_MOB_SLIME,
L"mob/spider", // eSoundType_MOB_SPIDER_AMBIENT, L"mob/slime/slimeattack", // eSoundType_MOB_SLIME_ATTACK,
L"mob/spiderdeath", // eSoundType_MOB_SPIDER_DEATH, L"mob/creeper/creeper", // eSoundType_MOB_CREEPER_HURT,
L"mob/slime", // eSoundType_MOB_SLIME, L"mob/creeper/creeperdeath", // eSoundType_MOB_CREEPER_DEATH,
L"mob/slimeattack", // eSoundType_MOB_SLIME_ATTACK, L"mob/zombie/zombie", // eSoundType_MOB_ZOMBIE_AMBIENT,
L"mob/creeper", // eSoundType_MOB_CREEPER_HURT, L"mob/zombie/zombiehurt", // eSoundType_MOB_ZOMBIE_HURT,
L"mob/creeperdeath", // eSoundType_MOB_CREEPER_DEATH, L"mob/zombie/zombiedeath", // eSoundType_MOB_ZOMBIE_DEATH,
L"mob/zombie", // eSoundType_MOB_ZOMBIE_AMBIENT, L"mob/zombie/wood", // eSoundType_MOB_ZOMBIE_WOOD,
L"mob/zombiehurt", // eSoundType_MOB_ZOMBIE_HURT, L"mob/zombie/woodbreak", // eSoundType_MOB_ZOMBIE_WOOD_BREAK,
L"mob/zombiedeath", // eSoundType_MOB_ZOMBIE_DEATH, L"mob/zombie/metal", // eSoundType_MOB_ZOMBIE_METAL,
L"mob/zombie/wood", // eSoundType_MOB_ZOMBIE_WOOD, L"mob/magmacube/big", // eSoundType_MOB_MAGMACUBE_BIG,
L"mob/zombie/woodbreak", // eSoundType_MOB_ZOMBIE_WOOD_BREAK, L"mob/magmacube/small", // eSoundType_MOB_MAGMACUBE_SMALL,
L"mob/zombie/metal", // eSoundType_MOB_ZOMBIE_METAL, L"mob/cat/purr", // eSoundType_MOB_CAT_PURR
L"mob/magmacube/big", // eSoundType_MOB_MAGMACUBE_BIG, L"mob/cat/purreow", // eSoundType_MOB_CAT_PURREOW
L"mob/magmacube/small", // eSoundType_MOB_MAGMACUBE_SMALL, L"mob/cat/meow", // eSoundType_MOB_CAT_MEOW
L"mob/cat/purr", // eSoundType_MOB_CAT_PURR // 4J-PB - correct the name of the event for hitting ocelots
L"mob/cat/purreow", // eSoundType_MOB_CAT_PURREOW L"mob/cat/hit", // eSoundType_MOB_CAT_HITT
L"mob/cat/meow", // eSoundType_MOB_CAT_MEOW // L"mob/irongolem/throw", //
// 4J-PB - correct the name of the event for hitting ocelots //eSoundType_MOB_IRONGOLEM_THROW L"mob/irongolem/hit",
L"mob/cat/hit", // eSoundType_MOB_CAT_HITT //// eSoundType_MOB_IRONGOLEM_HIT L"mob/irongolem/death",
// L"mob/irongolem/throw", // eSoundType_MOB_IRONGOLEM_THROW //// eSoundType_MOB_IRONGOLEM_DEATH L"mob/irongolem/walk",
// L"mob/irongolem/hit", // eSoundType_MOB_IRONGOLEM_HIT //// eSoundType_MOB_IRONGOLEM_WALK
// L"mob/irongolem/death", // eSoundType_MOB_IRONGOLEM_DEATH L"random/bow", // eSoundType_RANDOM_BOW,
// L"mob/irongolem/walk", // eSoundType_MOB_IRONGOLEM_WALK L"random/bowhit", // eSoundType_RANDOM_BOW_HIT,
L"random/bow", // eSoundType_RANDOM_BOW, L"random/explode", // eSoundType_RANDOM_EXPLODE,
L"random/bowhit", // eSoundType_RANDOM_BOW_HIT, L"random/fizz", // eSoundType_RANDOM_FIZZ,
L"random/explode", // eSoundType_RANDOM_EXPLODE, L"random/pop", // eSoundType_RANDOM_POP,
L"random/fizz", // eSoundType_RANDOM_FIZZ, L"random/fuse", // eSoundType_RANDOM_FUSE,
L"random/pop", // eSoundType_RANDOM_POP, L"random/drink", // eSoundType_RANDOM_DRINK,
L"random/fuse", // eSoundType_RANDOM_FUSE, L"random/eat", // eSoundType_RANDOM_EAT,
L"random/drink", // eSoundType_RANDOM_DRINK, L"random/burp", // eSoundType_RANDOM_BURP,
L"random/eat", // eSoundType_RANDOM_EAT, L"random/splash", // eSoundType_RANDOM_SPLASH,
L"random/burp", // eSoundType_RANDOM_BURP, L"random/click", // eSoundType_RANDOM_CLICK,
L"random/splash", // eSoundType_RANDOM_SPLASH, L"random/glass", // eSoundType_RANDOM_GLASS,
L"random/click", // eSoundType_RANDOM_CLICK, L"random/orb", // eSoundType_RANDOM_ORB,
L"random/glass", // eSoundType_RANDOM_GLASS, L"random/break", // eSoundType_RANDOM_BREAK,
L"random/orb", // eSoundType_RANDOM_ORB, L"random/chestopen", // eSoundType_RANDOM_CHEST_OPEN,
L"random/break", // eSoundType_RANDOM_BREAK, L"random/chestclosed", // eSoundType_RANDOM_CHEST_CLOSE,
L"random/chestopen", // eSoundType_RANDOM_CHEST_OPEN, L"random/door_open", // eSoundType_RANDOM_DOOR_OPEN,
L"random/chestclosed", // eSoundType_RANDOM_CHEST_CLOSE, L"random/door_close", // eSoundType_RANDOM_DOOR_CLOSE,
L"random/door_open", // eSoundType_RANDOM_DOOR_OPEN, L"ambient/weather/rain", // eSoundType_AMBIENT_WEATHER_RAIN,
L"random/door_close", // eSoundType_RANDOM_DOOR_CLOSE, L"ambient/weather/thunder", // eSoundType_AMBIENT_WEATHER_THUNDER,
L"ambient/weather/rain", // eSoundType_AMBIENT_WEATHER_RAIN, L"ambient/cave/cave", // eSoundType_CAVE_CAVE, DON'T USE FOR XBOX 360!!!
L"ambient/weather/thunder", // eSoundType_AMBIENT_WEATHER_THUNDER,
L"ambient/cave/cave", // eSoundType_CAVE_CAVE, DON'T USE FOR XBOX 360!!!
#ifdef _XBOX #ifdef _XBOX
L"ambient/cave/cave2", // eSoundType_CAVE_CAVE2 - removed the two sounds that were at 192k in the first ambient cave event L"ambient/cave/cave2", // eSoundType_CAVE_CAVE2 - removed the two sounds
//that were at 192k in the first ambient cave event
#endif #endif
L"portal/portal", // eSoundType_PORTAL_PORTAL, L"portal/portal", // eSoundType_PORTAL_PORTAL,
// 4J-PB - added a couple that were still using std::wstring // 4J-PB - added a couple that were still using std::wstring
L"portal/trigger", // eSoundType_PORTAL_TRIGGER L"portal/trigger", // eSoundType_PORTAL_TRIGGER
L"portal/travel", // eSoundType_PORTAL_TRAVEL L"portal/travel", // eSoundType_PORTAL_TRAVEL
L"fire/ignite", // eSoundType_FIRE_IGNITE,
L"fire/fire", // eSoundType_FIRE_FIRE,
L"damage/hurtflesh", // eSoundType_DAMAGE_HURT,
L"damage/fallsmall", // eSoundType_DAMAGE_FALL_SMALL,
L"damage/fallbig", // eSoundType_DAMAGE_FALL_BIG,
L"note/harp", // eSoundType_NOTE_HARP,
L"note/bd", // eSoundType_NOTE_BD,
L"note/snare", // eSoundType_NOTE_SNARE,
L"note/hat", // eSoundType_NOTE_HAT,
L"note/bassattack", // eSoundType_NOTE_BASSATTACK,
L"tile/piston/in", // eSoundType_TILE_PISTON_IN,
L"tile/piston/out", // eSoundType_TILE_PISTON_OUT,
L"liquid/water", // eSoundType_LIQUID_WATER,
L"liquid/lavapop", // eSoundType_LIQUID_LAVA_POP,
L"liquid/lava", // eSoundType_LIQUID_LAVA,
L"step/stone", // eSoundType_STEP_STONE,
L"step/wood", // eSoundType_STEP_WOOD,
L"step/gravel", // eSoundType_STEP_GRAVEL,
L"step/grass", // eSoundType_STEP_GRASS,
L"step/metal", // eSoundType_STEP_METAL,
L"step/cloth", // eSoundType_STEP_CLOTH,
L"step/sand", // eSoundType_STEP_SAND,
// below this are the additional sounds from the second soundbank
L"mob/enderdragon/end", // eSoundType_MOB_ENDERDRAGON_END
L"mob/enderdragon/growl", // eSoundType_MOB_ENDERDRAGON_GROWL
L"mob/enderdragon/hit", // eSoundType_MOB_ENDERDRAGON_HIT
L"mob/enderdragon/wings", // eSoundType_MOB_ENDERDRAGON_MOVE
L"mob/irongolem/throw", // eSoundType_MOB_IRONGOLEM_THROW
L"mob/irongolem/hit", // eSoundType_MOB_IRONGOLEM_HIT
L"mob/irongolem/death", // eSoundType_MOB_IRONGOLEM_DEATH
L"mob/irongolem/walk", // eSoundType_MOB_IRONGOLEM_WALK
// TU14 L"fire/ignite", // eSoundType_FIRE_IGNITE,
L"damage/thorns", // eSoundType_DAMAGE_THORNS L"fire/fire", // eSoundType_FIRE_FIRE,
L"random/anvil_break", // eSoundType_RANDOM_ANVIL_BREAK L"damage/hurtflesh", // eSoundType_DAMAGE_HURT,
L"random/anvil_land", // eSoundType_RANDOM_ANVIL_LAND L"damage/fallsmall", // eSoundType_DAMAGE_FALL_SMALL,
L"random/anvil_use", // eSoundType_RANDOM_ANVIL_USE L"damage/fallbig", // eSoundType_DAMAGE_FALL_BIG,
L"mob/villager/haggle", // eSoundType_MOB_VILLAGER_HAGGLE L"note/harp", // eSoundType_NOTE_HARP,
L"mob/villager/idle", // eSoundType_MOB_VILLAGER_IDLE L"note/bd", // eSoundType_NOTE_BD,
L"mob/villager/hit", // eSoundType_MOB_VILLAGER_HIT L"note/snare", // eSoundType_NOTE_SNARE,
L"mob/villager/death", // eSoundType_MOB_VILLAGER_DEATH L"note/hat", // eSoundType_NOTE_HAT,
L"mob/villager/yes", // eSoundType_MOB_VILLAGER_YES L"note/bassattack", // eSoundType_NOTE_BASSATTACK,
L"mob/villager/no", // eSoundType_MOB_VILLAGER_NO L"tile/piston/in", // eSoundType_TILE_PISTON_IN,
L"mob/zombie/infect", // eSoundType_MOB_ZOMBIE_INFECT L"tile/piston/out", // eSoundType_TILE_PISTON_OUT,
L"mob/zombie/unfect", // eSoundType_MOB_ZOMBIE_UNFECT L"liquid/water", // eSoundType_LIQUID_WATER,
L"mob/zombie/remedy", // eSoundType_MOB_ZOMBIE_REMEDY L"liquid/lavapop", // eSoundType_LIQUID_LAVA_POP,
L"step/snow", // eSoundType_STEP_SNOW L"liquid/lava", // eSoundType_LIQUID_LAVA,
L"step/ladder", // eSoundType_STEP_LADDER L"step/stone", // eSoundType_STEP_STONE,
L"dig/cloth", // eSoundType_DIG_CLOTH L"step/wood", // eSoundType_STEP_WOOD,
L"dig/grass", // eSoundType_DIG_GRASS L"step/gravel", // eSoundType_STEP_GRAVEL,
L"dig/gravel", // eSoundType_DIG_GRAVEL L"step/grass", // eSoundType_STEP_GRASS,
L"dig/sand", // eSoundType_DIG_SAND L"step/metal", // eSoundType_STEP_METAL,
L"dig/snow", // eSoundType_DIG_SNOW L"step/cloth", // eSoundType_STEP_CLOTH,
L"dig/stone", // eSoundType_DIG_STONE L"step/sand", // eSoundType_STEP_SAND,
L"dig/wood", // eSoundType_DIG_WOOD
// below this are the additional sounds from the second soundbank
L"mob/enderdragon/end", // eSoundType_MOB_ENDERDRAGON_END
L"mob/enderdragon/growl", // eSoundType_MOB_ENDERDRAGON_GROWL
L"mob/enderdragon/hit", // eSoundType_MOB_ENDERDRAGON_HIT
L"mob/enderdragon/wings", // eSoundType_MOB_ENDERDRAGON_MOVE
L"mob/irongolem/throw", // eSoundType_MOB_IRONGOLEM_THROW
L"mob/irongolem/hit", // eSoundType_MOB_IRONGOLEM_HIT
L"mob/irongolem/death", // eSoundType_MOB_IRONGOLEM_DEATH
L"mob/irongolem/walk", // eSoundType_MOB_IRONGOLEM_WALK
// TU14
// For some reason damage/thorns is missing...
L"damage/thorns", // eSoundType_DAMAGE_THORNS
L"random/anvil_break", // eSoundType_RANDOM_ANVIL_BREAK
L"random/anvil_land", // eSoundType_RANDOM_ANVIL_LAND
L"random/anvil_use", // eSoundType_RANDOM_ANVIL_USE
L"mob/villager/haggle", // eSoundType_MOB_VILLAGER_HAGGLE
L"mob/villager/idle", // eSoundType_MOB_VILLAGER_IDLE
L"mob/villager/hit", // eSoundType_MOB_VILLAGER_HIT
L"mob/villager/death", // eSoundType_MOB_VILLAGER_DEATH
L"mob/villager/yes", // eSoundType_MOB_VILLAGER_YES
L"mob/villager/no", // eSoundType_MOB_VILLAGER_NO
L"mob/zombie/infect", // eSoundType_MOB_ZOMBIE_INFECT
L"mob/zombie/unfect", // eSoundType_MOB_ZOMBIE_UNFECT
L"mob/zombie/remedy", // eSoundType_MOB_ZOMBIE_REMEDY
L"step/snow", // eSoundType_STEP_SNOW
L"step/ladder", // eSoundType_STEP_LADDER
L"dig/cloth", // eSoundType_DIG_CLOTH
L"dig/grass", // eSoundType_DIG_GRASS
L"dig/gravel", // eSoundType_DIG_GRAVEL
L"dig/sand", // eSoundType_DIG_SAND
L"dig/snow", // eSoundType_DIG_SNOW
L"dig/stone", // eSoundType_DIG_STONE
L"dig/wood", // eSoundType_DIG_WOOD
}; };
const WCHAR* ConsoleSoundEngine::wchUISoundNames[eSFX_MAX] = {
const WCHAR *ConsoleSoundEngine::wchUISoundNames[eSFX_MAX]= L"back", L"craft", L"craftfail", L"focus", L"press", L"scroll",
{
L"back",
L"craft",
L"craftfail",
L"focus",
L"press",
L"scroll",
}; };

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,591 @@
#ifndef miniaudio_libvorbis_c
#define miniaudio_libvorbis_c
#include "miniaudio_libvorbis.h"
#if !defined(MA_NO_LIBVORBIS)
#ifndef OV_EXCLUDE_STATIC_CALLBACKS
#define OV_EXCLUDE_STATIC_CALLBACKS
#endif
#include <vorbis/vorbisfile.h>
#endif
#include <string.h> /* For memset(). */
#include <assert.h>
static ma_result ma_libvorbis_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
return ma_libvorbis_read_pcm_frames((ma_libvorbis*)pDataSource, pFramesOut, frameCount, pFramesRead);
}
static ma_result ma_libvorbis_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
return ma_libvorbis_seek_to_pcm_frame((ma_libvorbis*)pDataSource, frameIndex);
}
static ma_result ma_libvorbis_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
return ma_libvorbis_get_data_format((ma_libvorbis*)pDataSource, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
}
static ma_result ma_libvorbis_ds_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
{
return ma_libvorbis_get_cursor_in_pcm_frames((ma_libvorbis*)pDataSource, pCursor);
}
static ma_result ma_libvorbis_ds_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
{
return ma_libvorbis_get_length_in_pcm_frames((ma_libvorbis*)pDataSource, pLength);
}
static ma_data_source_vtable g_ma_libvorbis_ds_vtable =
{
ma_libvorbis_ds_read,
ma_libvorbis_ds_seek,
ma_libvorbis_ds_get_data_format,
ma_libvorbis_ds_get_cursor,
ma_libvorbis_ds_get_length,
NULL, /* onSetLooping */
0 /* flags */
};
#if !defined(MA_NO_LIBVORBIS)
static size_t ma_libvorbis_vf_callback__read(void* pBufferOut, size_t size, size_t count, void* pUserData)
{
ma_libvorbis* pVorbis = (ma_libvorbis*)pUserData;
ma_result result;
size_t bytesToRead;
size_t bytesRead;
/* For consistency with fread(). If `size` of `count` is 0, return 0 immediately without changing anything. */
if (size == 0 || count == 0) {
return 0;
}
bytesToRead = size * count;
result = pVorbis->onRead(pVorbis->pReadSeekTellUserData, pBufferOut, bytesToRead, &bytesRead);
if (result != MA_SUCCESS) {
/* Not entirely sure what to return here. What if an error occurs, but some data was read and bytesRead is > 0? */
return 0;
}
return bytesRead / size;
}
static int ma_libvorbis_vf_callback__seek(void* pUserData, ogg_int64_t offset, int whence)
{
ma_libvorbis* pVorbis = (ma_libvorbis*)pUserData;
ma_result result;
ma_seek_origin origin;
if (whence == SEEK_SET) {
origin = ma_seek_origin_start;
} else if (whence == SEEK_END) {
origin = ma_seek_origin_end;
} else {
origin = ma_seek_origin_current;
}
result = pVorbis->onSeek(pVorbis->pReadSeekTellUserData, offset, origin);
if (result != MA_SUCCESS) {
return -1;
}
return 0;
}
static long ma_libvorbis_vf_callback__tell(void* pUserData)
{
ma_libvorbis* pVorbis = (ma_libvorbis*)pUserData;
ma_result result;
ma_int64 cursor;
result = pVorbis->onTell(pVorbis->pReadSeekTellUserData, &cursor);
if (result != MA_SUCCESS) {
return -1;
}
return (long)cursor;
}
#endif
static ma_result ma_libvorbis_init_internal(const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_libvorbis* pVorbis)
{
if (pVorbis == NULL) {
return MA_INVALID_ARGS;
}
memset(pVorbis, 0, sizeof(*pVorbis));
pVorbis->format = ma_format_f32; /* f32 by default. */
if (pConfig != NULL && (pConfig->preferredFormat == ma_format_f32 || pConfig->preferredFormat == ma_format_s16)) {
pVorbis->format = pConfig->preferredFormat;
} else {
/* Getting here means something other than f32 and s16 was specified. Just leave this unset to use the default format. */
}
#if !defined(MA_NO_LIBVORBIS)
{
ma_result result;
ma_data_source_config dataSourceConfig;
dataSourceConfig = ma_data_source_config_init();
dataSourceConfig.vtable = &g_ma_libvorbis_ds_vtable;
result = ma_data_source_init(&dataSourceConfig, &pVorbis->ds);
if (result != MA_SUCCESS) {
return result; /* Failed to initialize the base data source. */
}
pVorbis->vf = (OggVorbis_File*)ma_malloc(sizeof(OggVorbis_File), pAllocationCallbacks);
if (pVorbis->vf == NULL) {
ma_data_source_uninit(&pVorbis->ds);
return MA_OUT_OF_MEMORY;
}
return MA_SUCCESS;
}
#else
{
/* libvorbis is disabled. */
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_libvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_libvorbis* pVorbis)
{
ma_result result;
(void)pAllocationCallbacks; /* Can't seem to find a way to configure memory allocations in libvorbis. */
if (onRead == NULL || onSeek == NULL) {
return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
}
result = ma_libvorbis_init_internal(pConfig, pAllocationCallbacks, pVorbis);
if (result != MA_SUCCESS) {
return result;
}
pVorbis->onRead = onRead;
pVorbis->onSeek = onSeek;
pVorbis->onTell = onTell;
pVorbis->pReadSeekTellUserData = pReadSeekTellUserData;
#if !defined(MA_NO_LIBVORBIS)
{
int libvorbisResult;
ov_callbacks libvorbisCallbacks;
/* We can now initialize the vorbis decoder. This must be done after we've set up the callbacks. */
libvorbisCallbacks.read_func = ma_libvorbis_vf_callback__read;
libvorbisCallbacks.seek_func = ma_libvorbis_vf_callback__seek;
libvorbisCallbacks.close_func = NULL;
libvorbisCallbacks.tell_func = ma_libvorbis_vf_callback__tell;
libvorbisResult = ov_open_callbacks(pVorbis, (OggVorbis_File*)pVorbis->vf, NULL, 0, libvorbisCallbacks);
if (libvorbisResult < 0) {
ma_data_source_uninit(&pVorbis->ds);
ma_free(pVorbis->vf, pAllocationCallbacks);
return MA_INVALID_FILE;
}
return MA_SUCCESS;
}
#else
{
/* libvorbis is disabled. */
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_libvorbis_init_file(const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_libvorbis* pVorbis)
{
ma_result result;
(void)pAllocationCallbacks; /* Can't seem to find a way to configure memory allocations in libvorbis. */
result = ma_libvorbis_init_internal(pConfig, pAllocationCallbacks, pVorbis);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_LIBVORBIS)
{
int libvorbisResult;
libvorbisResult = ov_fopen(pFilePath, (OggVorbis_File*)pVorbis->vf);
if (libvorbisResult < 0) {
ma_data_source_uninit(&pVorbis->ds);
ma_free(pVorbis->vf, pAllocationCallbacks);
return MA_INVALID_FILE;
}
return MA_SUCCESS;
}
#else
{
/* libvorbis is disabled. */
(void)pFilePath;
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API void ma_libvorbis_uninit(ma_libvorbis* pVorbis, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pVorbis == NULL) {
return;
}
(void)pAllocationCallbacks;
#if !defined(MA_NO_LIBVORBIS)
{
ov_clear((OggVorbis_File*)pVorbis->vf);
}
#else
{
/* libvorbis is disabled. Should never hit this since initialization would have failed. */
assert(MA_FALSE);
}
#endif
ma_data_source_uninit(&pVorbis->ds);
ma_free(pVorbis->vf, pAllocationCallbacks);
}
MA_API ma_result ma_libvorbis_read_pcm_frames(ma_libvorbis* pVorbis, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
if (pFramesRead != NULL) {
*pFramesRead = 0;
}
if (frameCount == 0) {
return MA_INVALID_ARGS;
}
if (pVorbis == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_LIBVORBIS)
{
/* We always use floating point format. */
ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
ma_uint64 totalFramesRead;
ma_format format;
ma_uint32 channels;
ma_libvorbis_get_data_format(pVorbis, &format, &channels, NULL, NULL, 0);
totalFramesRead = 0;
while (totalFramesRead < frameCount) {
long libvorbisResult;
ma_uint64 framesToRead;
ma_uint64 framesRemaining;
framesRemaining = (frameCount - totalFramesRead);
framesToRead = 1024;
if (framesToRead > framesRemaining) {
framesToRead = framesRemaining;
}
if (format == ma_format_f32) {
float** ppFramesF32;
libvorbisResult = ov_read_float((OggVorbis_File*)pVorbis->vf, &ppFramesF32, (int)framesToRead, NULL);
if (libvorbisResult < 0) {
result = MA_ERROR; /* Error while decoding. */
break;
} else {
/* Frames need to be interleaved. */
ma_interleave_pcm_frames(format, channels, libvorbisResult, (const void**)ppFramesF32, ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, format, channels));
totalFramesRead += libvorbisResult;
if (libvorbisResult == 0) {
result = MA_AT_END;
break;
}
}
} else {
libvorbisResult = ov_read((OggVorbis_File*)pVorbis->vf, (char*)ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, format, channels), (int)(framesToRead * ma_get_bytes_per_frame(format, channels)), 0, 2, 1, NULL);
if (libvorbisResult < 0) {
result = MA_ERROR; /* Error while decoding. */
break;
} else {
/* Conveniently, there's no need to interleaving when using ov_read(). I'm not sure why ov_read_float() is different in that regard... */
totalFramesRead += libvorbisResult / ma_get_bytes_per_frame(format, channels);
if (libvorbisResult == 0) {
result = MA_AT_END;
break;
}
}
}
}
if (pFramesRead != NULL) {
*pFramesRead = totalFramesRead;
}
if (result == MA_SUCCESS && totalFramesRead == 0) {
result = MA_AT_END;
}
return result;
}
#else
{
/* libvorbis is disabled. Should never hit this since initialization would have failed. */
assert(MA_FALSE);
(void)pFramesOut;
(void)frameCount;
(void)pFramesRead;
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_libvorbis_seek_to_pcm_frame(ma_libvorbis* pVorbis, ma_uint64 frameIndex)
{
if (pVorbis == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_LIBVORBIS)
{
int libvorbisResult = ov_pcm_seek((OggVorbis_File*)pVorbis->vf, (ogg_int64_t)frameIndex);
if (libvorbisResult != 0) {
if (libvorbisResult == OV_ENOSEEK) {
return MA_INVALID_OPERATION; /* Not seekable. */
} else if (libvorbisResult == OV_EINVAL) {
return MA_INVALID_ARGS;
} else {
return MA_ERROR;
}
}
return MA_SUCCESS;
}
#else
{
/* libvorbis is disabled. Should never hit this since initialization would have failed. */
assert(MA_FALSE);
(void)frameIndex;
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_libvorbis_get_data_format(ma_libvorbis* pVorbis, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
/* Defaults for safety. */
if (pFormat != NULL) {
*pFormat = ma_format_unknown;
}
if (pChannels != NULL) {
*pChannels = 0;
}
if (pSampleRate != NULL) {
*pSampleRate = 0;
}
if (pChannelMap != NULL) {
memset(pChannelMap, 0, sizeof(*pChannelMap) * channelMapCap);
}
if (pVorbis == NULL) {
return MA_INVALID_OPERATION;
}
if (pFormat != NULL) {
*pFormat = pVorbis->format;
}
#if !defined(MA_NO_LIBVORBIS)
{
vorbis_info* pInfo = ov_info((OggVorbis_File*)pVorbis->vf, 0);
if (pInfo == NULL) {
return MA_INVALID_OPERATION;
}
if (pChannels != NULL) {
*pChannels = pInfo->channels;
}
if (pSampleRate != NULL) {
*pSampleRate = pInfo->rate;
}
if (pChannelMap != NULL) {
ma_channel_map_init_standard(ma_standard_channel_map_vorbis, pChannelMap, channelMapCap, pInfo->channels);
}
return MA_SUCCESS;
}
#else
{
/* libvorbis is disabled. Should never hit this since initialization would have failed. */
assert(MA_FALSE);
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_libvorbis_get_cursor_in_pcm_frames(ma_libvorbis* pVorbis, ma_uint64* pCursor)
{
if (pCursor == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = 0; /* Safety. */
if (pVorbis == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_LIBVORBIS)
{
ogg_int64_t offset = ov_pcm_tell((OggVorbis_File*)pVorbis->vf);
if (offset < 0) {
return MA_INVALID_FILE;
}
*pCursor = (ma_uint64)offset;
return MA_SUCCESS;
}
#else
{
/* libvorbis is disabled. Should never hit this since initialization would have failed. */
assert(MA_FALSE);
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_libvorbis_get_length_in_pcm_frames(ma_libvorbis* pVorbis, ma_uint64* pLength)
{
if (pLength == NULL) {
return MA_INVALID_ARGS;
}
*pLength = 0; /* Safety. */
if (pVorbis == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_LIBVORBIS)
{
/*
Will work in the supermajority of cases where a file has a single logical bitstream. Concatenated streams
are much harder to determine the length of since they can have sample rate changes, but they should be
extremely rare outside of unseekable livestreams anyway.
*/
if (ov_streams((OggVorbis_File*)pVorbis->vf) == 1) {
ogg_int64_t length = ov_pcm_total((OggVorbis_File*)pVorbis->vf, 0);
if(length != OV_EINVAL) {
*pLength = (ma_uint64)length;
} else {
/* Unseekable. */
}
} else {
/* Concatenated stream. */
}
return MA_SUCCESS;
}
#else
{
/* libvorbis is disabled. Should never hit this since initialization would have failed. */
assert(MA_FALSE);
return MA_NOT_IMPLEMENTED;
}
#endif
}
/*
The code below defines the vtable that you'll plug into your `ma_decoder_config` object.
*/
#if !defined(MA_NO_LIBVORBIS)
static ma_result ma_decoding_backend_init__libvorbis(void* pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
{
ma_result result;
ma_libvorbis* pVorbis;
(void)pUserData;
pVorbis = (ma_libvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
if (pVorbis == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_libvorbis_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pVorbis);
if (result != MA_SUCCESS) {
ma_free(pVorbis, pAllocationCallbacks);
return result;
}
*ppBackend = pVorbis;
return MA_SUCCESS;
}
static ma_result ma_decoding_backend_init_file__libvorbis(void* pUserData, const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
{
ma_result result;
ma_libvorbis* pVorbis;
(void)pUserData;
pVorbis = (ma_libvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
if (pVorbis == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_libvorbis_init_file(pFilePath, pConfig, pAllocationCallbacks, pVorbis);
if (result != MA_SUCCESS) {
ma_free(pVorbis, pAllocationCallbacks);
return result;
}
*ppBackend = pVorbis;
return MA_SUCCESS;
}
static void ma_decoding_backend_uninit__libvorbis(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_libvorbis* pVorbis = (ma_libvorbis*)pBackend;
(void)pUserData;
ma_libvorbis_uninit(pVorbis, pAllocationCallbacks);
ma_free(pVorbis, pAllocationCallbacks);
}
static ma_decoding_backend_vtable ma_gDecodingBackendVTable_libvorbis =
{
ma_decoding_backend_init__libvorbis,
ma_decoding_backend_init_file__libvorbis,
NULL, /* onInitFileW() */
NULL, /* onInitMemory() */
ma_decoding_backend_uninit__libvorbis
};
ma_decoding_backend_vtable* ma_decoding_backend_libvorbis = &ma_gDecodingBackendVTable_libvorbis;
#else
ma_decoding_backend_vtable* ma_decoding_backend_libvorbis = NULL;
#endif
#endif /* miniaudio_libvorbis_c */

View file

@ -0,0 +1,42 @@
/*
This implements a data source that decodes Vorbis streams via libvorbis + libvorbisfile
This object can be plugged into any `ma_data_source_*()` API and can also be used as a custom
decoding backend. See the custom_decoder example.
*/
#ifndef miniaudio_libvorbis_h
#define miniaudio_libvorbis_h
#ifdef __cplusplus
extern "C" {
#endif
#include "../../../miniaudio.h"
typedef struct
{
ma_data_source_base ds; /* The libvorbis decoder can be used independently as a data source. */
ma_read_proc onRead;
ma_seek_proc onSeek;
ma_tell_proc onTell;
void* pReadSeekTellUserData;
ma_format format; /* Will be either f32 or s16. */
/*OggVorbis_File**/ void* vf; /* Typed as void* so we can avoid a dependency on opusfile in the header section. */
} ma_libvorbis;
MA_API ma_result ma_libvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_libvorbis* pVorbis);
MA_API ma_result ma_libvorbis_init_file(const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_libvorbis* pVorbis);
MA_API void ma_libvorbis_uninit(ma_libvorbis* pVorbis, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_libvorbis_read_pcm_frames(ma_libvorbis* pVorbis, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_libvorbis_seek_to_pcm_frame(ma_libvorbis* pVorbis, ma_uint64 frameIndex);
MA_API ma_result ma_libvorbis_get_data_format(ma_libvorbis* pVorbis, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
MA_API ma_result ma_libvorbis_get_cursor_in_pcm_frames(ma_libvorbis* pVorbis, ma_uint64* pCursor);
MA_API ma_result ma_libvorbis_get_length_in_pcm_frames(ma_libvorbis* pVorbis, ma_uint64* pLength);
/* Decoding backend vtable. This is what you'll plug into ma_decoder_config.pBackendVTables. No user data required. */
extern ma_decoding_backend_vtable* ma_decoding_backend_libvorbis;
#ifdef __cplusplus
}
#endif
#endif /* miniaudio_libvorbis_h */

File diff suppressed because it is too large Load diff