mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 02:56:09 -04:00
start porting audio to C client
This commit is contained in:
parent
0d75633ec0
commit
daaa68cea2
@ -16,8 +16,6 @@ namespace ClassicalSharp.Audio {
|
||||
}
|
||||
|
||||
public class Soundboard {
|
||||
|
||||
public byte[] Data;
|
||||
List<SoundGroup> groups = new List<SoundGroup>();
|
||||
Random rnd = new Random();
|
||||
|
||||
|
1560
src/Client/Audio.c
1560
src/Client/Audio.c
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,6 @@
|
||||
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
*/
|
||||
struct IGameComponent;
|
||||
struct Stream;
|
||||
|
||||
void Audio_MakeComponent(struct IGameComponent* comp);
|
||||
void Audio_SetMusic(Int32 volume);
|
||||
@ -13,43 +12,4 @@ void Audio_SetSounds(Int32 volume);
|
||||
void Audio_PlayDigSound(UInt8 type);
|
||||
void Audio_PlayStepSound(UInt8 type);
|
||||
|
||||
enum OGG_VER { OGG_ERR_INVALID_SIG = 2552401, OGG_ERR_VERSION };
|
||||
#define OGG_BUFFER_SIZE (255 * 256)
|
||||
void Ogg_MakeStream(struct Stream* stream, UInt8* buffer, struct Stream* source);
|
||||
|
||||
enum VORBIS_ERR {
|
||||
VORBIS_ERR_HEADER = 5238001, VORBIS_ERR_WRONG_HEADER, VORBIS_ERR_FRAMING,
|
||||
VORBIS_ERR_VERSION, VORBIS_ERR_BLOCKSIZE, VORBIS_ERR_CHANS,
|
||||
VORBIS_ERR_TIME_TYPE, VORBIS_ERR_FLOOR_TYPE, VORBIS_ERR_RESIDUE_TYPE,
|
||||
VORBIS_ERR_MAPPING_TYPE, VORBIS_ERR_MODE_TYPE,
|
||||
VORBIS_ERR_CODEBOOK_SYNC, VORBIS_ERR_CODEBOOK_ENTRY, VORBIS_ERR_CODEBOOK_LOOKUP,
|
||||
VORBIS_ERR_MODE_WINDOW, VORBIS_ERR_MODE_TRANSFORM,
|
||||
VORBIS_ERR_MAPPING_CHANS, VORBIS_ERR_MAPPING_RESERVED,
|
||||
VORBIS_ERR_FRAME_TYPE,
|
||||
};
|
||||
|
||||
#define VORBIS_MAX_CHANS 8
|
||||
struct Codebook; struct Floor; struct Residue; struct Mapping; struct Mode;
|
||||
struct VorbisState {
|
||||
UInt32 Bits; /* Holds bits across byte boundaries*/
|
||||
UInt32 NumBits; /* Number of bits in Bits buffer*/
|
||||
struct Stream* Source; /* Source for filling Input buffer */
|
||||
|
||||
UInt8 Channels, ModeNumBits;
|
||||
UInt16 CurBlockSize, PrevBlockSize, DataSize;
|
||||
Int32 SampleRate; Int32 BlockSizes[2];
|
||||
Real32* Values;
|
||||
Real32* PrevOutput[VORBIS_MAX_CHANS];
|
||||
Real32* CurOutput[VORBIS_MAX_CHANS];
|
||||
|
||||
struct Codebook* Codebooks;
|
||||
struct Floor* Floors;
|
||||
struct Residue* Residues;
|
||||
struct Mapping* Mappings;
|
||||
struct Mode* Modes;
|
||||
};
|
||||
void Vorbis_Init(struct VorbisState* ctx, struct Stream* source);
|
||||
ReturnCode Vorbis_DecodeHeaders(struct VorbisState* ctx);
|
||||
ReturnCode Vorbis_DecodeFrame(struct VorbisState* ctx);
|
||||
Int32 Vorbis_OutputFrame(struct VorbisState* ctx, Int16* data);
|
||||
#endif
|
||||
|
@ -99,7 +99,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<MinimumRequiredVersion>5.02</MinimumRequiredVersion>
|
||||
<EntryPointSymbol>main</EntryPointSymbol>
|
||||
<AdditionalDependencies>d3d9.lib;opengl32.lib;ucrtd.lib;vcruntimed.lib;msvcrtd.lib;dbghelp.lib;ws2_32.lib;Wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d9.lib;opengl32.lib;ws2_32.lib;Wininet.lib;dbghelp.lib;Winmm.lib;ucrtd.lib;vcruntimed.lib;msvcrtd.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@ -119,7 +119,7 @@
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EntryPointSymbol>main</EntryPointSymbol>
|
||||
<AdditionalDependencies>d3d9.lib;opengl32.lib;ucrtd.lib;vcruntimed.lib;msvcrtd.lib;dbghelp.lib;ws2_32.lib;Wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d9.lib;opengl32.lib;ws2_32.lib;Wininet.lib;dbghelp.lib;Winmm.lib;ucrtd.lib;vcruntimed.lib;msvcrtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
@ -148,7 +148,7 @@
|
||||
<MinimumRequiredVersion>5.02</MinimumRequiredVersion>
|
||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||
<EntryPointSymbol>main</EntryPointSymbol>
|
||||
<AdditionalDependencies>d3d9.lib;opengl32.lib;libucrt.lib;libvcruntime.lib;dbghelp.lib;ws2_32.lib;Wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d9.lib;opengl32.lib;ws2_32.lib;Wininet.lib;dbghelp.lib;Winmm.lib;libucrt.lib;libvcruntime.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
@ -175,7 +175,7 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EntryPointSymbol>main</EntryPointSymbol>
|
||||
<AdditionalDependencies>d3d9.lib;opengl32.lib;libucrt.lib;libvcruntime.lib;dbghelp.lib;ws2_32.lib;Wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d9.lib;opengl32.lib;ws2_32.lib;Wininet.lib;dbghelp.lib;Winmm.lib;libucrt.lib;libvcruntime.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
@ -242,6 +242,7 @@
|
||||
<ClInclude Include="Typedefs.h" />
|
||||
<ClInclude Include="Vectors.h" />
|
||||
<ClInclude Include="VertexStructs.h" />
|
||||
<ClInclude Include="Vorbis.h" />
|
||||
<ClInclude Include="Widgets.h" />
|
||||
<ClInclude Include="Window.h" />
|
||||
<ClInclude Include="World.h" />
|
||||
@ -306,6 +307,7 @@
|
||||
<ClCompile Include="TexturePack.c" />
|
||||
<ClCompile Include="Utils.c" />
|
||||
<ClCompile Include="Vectors.c" />
|
||||
<ClCompile Include="Vorbis.c" />
|
||||
<ClCompile Include="Widgets.c" />
|
||||
<ClCompile Include="WinErrorHandler.c" />
|
||||
<ClCompile Include="WinPlatform.c" />
|
||||
|
@ -136,6 +136,12 @@
|
||||
<Filter Include="Header Files\Game">
|
||||
<UniqueIdentifier>{570b92b8-b3df-40cb-a42a-da14c81c877a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Audio">
|
||||
<UniqueIdentifier>{fee32b2d-e320-4681-9d5d-9904ca911271}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Audio">
|
||||
<UniqueIdentifier>{b6f24d6b-c6f6-4909-9ae1-f0c478846c6e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Typedefs.h">
|
||||
@ -321,9 +327,6 @@
|
||||
<ClInclude Include="TexturePack.h">
|
||||
<Filter>Header Files\TexturePack</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Audio.h">
|
||||
<Filter>Header Files\Game</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PacketHandlers.h">
|
||||
<Filter>Header Files\Network</Filter>
|
||||
</ClInclude>
|
||||
@ -336,6 +339,12 @@
|
||||
<ClInclude Include="EnvRenderer.h">
|
||||
<Filter>Header Files\Rendering</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Audio.h">
|
||||
<Filter>Header Files\Audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Vorbis.h">
|
||||
<Filter>Header Files\Audio</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="WinPlatform.c">
|
||||
@ -531,7 +540,10 @@
|
||||
<Filter>Source Files\Platform</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Audio.c">
|
||||
<Filter>Source Files\Game</Filter>
|
||||
<Filter>Source Files\Audio</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Vorbis.c">
|
||||
<Filter>Source Files\Audio</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -112,4 +112,15 @@ ReturnCode Platform_HttpGetRequestHeaders(struct AsyncRequest* request, void* ha
|
||||
ReturnCode Platform_HttpGetRequestData(struct AsyncRequest* request, void* handle, void** data, UInt32 size, volatile Int32* progress);
|
||||
ReturnCode Platform_HttpFreeRequest(void* handle);
|
||||
ReturnCode Platform_HttpFree(void);
|
||||
|
||||
#define AUDIO_MAX_CHUNKS 5
|
||||
struct AudioFormat { UInt8 Channels, BitsPerSample; UInt16 Frequency };
|
||||
#define AudioFormat_Eq(a, b) (a->Channels == b->Channels && a->BitsPerSample == b->BitsPerSample && a->Frequency == b->Frequency)
|
||||
|
||||
void Platform_AudioInit(Int32* handle, UInt8 buffers);
|
||||
void Platform_AudioFree(Int32 handle);
|
||||
void Platform_AudioSetFormat(Int32 handle, struct AudioFormat* format);
|
||||
void Platform_AudioPlayAsync(Int32 handle, void* data, UInt32 dataSize);
|
||||
Int32 Platform_AudioNextFinishedAsync(Int32 handle);
|
||||
bool Platform_AudioFinishedAsync(Int32 handle);
|
||||
#endif
|
||||
|
1337
src/Client/Vorbis.c
Normal file
1337
src/Client/Vorbis.c
Normal file
File diff suppressed because it is too large
Load Diff
49
src/Client/Vorbis.h
Normal file
49
src/Client/Vorbis.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef CC_VORBIS_H
|
||||
#define CC_VORBIS_H
|
||||
#include "Typedefs.h"
|
||||
/* Decodes ogg vorbis audio
|
||||
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
*/
|
||||
struct IGameComponent;
|
||||
struct Stream;
|
||||
|
||||
enum OGG_VER { OGG_ERR_INVALID_SIG = 2552401, OGG_ERR_VERSION };
|
||||
#define OGG_BUFFER_SIZE (255 * 256)
|
||||
void Ogg_MakeStream(struct Stream* stream, UInt8* buffer, struct Stream* source);
|
||||
|
||||
enum VORBIS_ERR {
|
||||
VORBIS_ERR_HEADER = 5238001, VORBIS_ERR_WRONG_HEADER, VORBIS_ERR_FRAMING,
|
||||
VORBIS_ERR_VERSION, VORBIS_ERR_BLOCKSIZE, VORBIS_ERR_CHANS,
|
||||
VORBIS_ERR_TIME_TYPE, VORBIS_ERR_FLOOR_TYPE, VORBIS_ERR_RESIDUE_TYPE,
|
||||
VORBIS_ERR_MAPPING_TYPE, VORBIS_ERR_MODE_TYPE,
|
||||
VORBIS_ERR_CODEBOOK_SYNC, VORBIS_ERR_CODEBOOK_ENTRY, VORBIS_ERR_CODEBOOK_LOOKUP,
|
||||
VORBIS_ERR_MODE_WINDOW, VORBIS_ERR_MODE_TRANSFORM,
|
||||
VORBIS_ERR_MAPPING_CHANS, VORBIS_ERR_MAPPING_RESERVED,
|
||||
VORBIS_ERR_FRAME_TYPE,
|
||||
};
|
||||
|
||||
#define VORBIS_MAX_CHANS 8
|
||||
struct Codebook; struct Floor; struct Residue; struct Mapping; struct Mode;
|
||||
struct VorbisState {
|
||||
UInt32 Bits; /* Holds bits across byte boundaries*/
|
||||
UInt32 NumBits; /* Number of bits in Bits buffer*/
|
||||
struct Stream* Source; /* Source for filling Input buffer */
|
||||
|
||||
UInt8 Channels, ModeNumBits;
|
||||
UInt16 CurBlockSize, PrevBlockSize, DataSize;
|
||||
Int32 SampleRate; Int32 BlockSizes[2];
|
||||
Real32* Values;
|
||||
Real32* PrevOutput[VORBIS_MAX_CHANS];
|
||||
Real32* CurOutput[VORBIS_MAX_CHANS];
|
||||
|
||||
struct Codebook* Codebooks;
|
||||
struct Floor* Floors;
|
||||
struct Residue* Residues;
|
||||
struct Mapping* Mappings;
|
||||
struct Mode* Modes;
|
||||
};
|
||||
void Vorbis_Init(struct VorbisState* ctx, struct Stream* source);
|
||||
ReturnCode Vorbis_DecodeHeaders(struct VorbisState* ctx);
|
||||
ReturnCode Vorbis_DecodeFrame(struct VorbisState* ctx);
|
||||
Int32 Vorbis_OutputFrame(struct VorbisState* ctx, Int16* data);
|
||||
#endif
|
@ -16,6 +16,7 @@
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <wininet.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
/* Missing from some old MingW32 headers */
|
||||
#define HTTP_QUERY_ETAG 54
|
||||
@ -597,4 +598,97 @@ ReturnCode Platform_HttpFreeRequest(void* handle) {
|
||||
ReturnCode Platform_HttpFree(void) {
|
||||
return InternetCloseHandle(hInternet) ? 0 : GetLastError();
|
||||
}
|
||||
|
||||
|
||||
struct AudioContext {
|
||||
HWAVEOUT Handle;
|
||||
WAVEHDR Headers[AUDIO_MAX_CHUNKS];
|
||||
struct AudioFormat Format;
|
||||
UInt8 NumBuffers, PlayingAsync;
|
||||
};
|
||||
struct AudioContext Audio_Contexts[20];
|
||||
|
||||
void Platform_AudioInit(Int32* handle, UInt8 buffers) {
|
||||
Int32 i;
|
||||
for (i = 0; i < Array_Elems(Audio_Contexts); i++) {
|
||||
struct AudioContext* ctx = &Audio_Contexts[i];
|
||||
if (ctx->NumBuffers) continue;
|
||||
|
||||
ctx->NumBuffers = buffers;
|
||||
*handle = i; return;
|
||||
}
|
||||
ErrorHandler_Fail("No free audio contexts");
|
||||
}
|
||||
|
||||
void Platform_AudioFree(Int32 handle) {
|
||||
struct AudioContext* ctx = &Audio_Contexts[handle];
|
||||
if (!ctx->Handle) return;
|
||||
|
||||
ReturnCode result = waveOutClose(ctx->Handle);
|
||||
Platform_MemSet(ctx, 0, sizeof(struct AudioContext));
|
||||
ErrorHandler_CheckOrFail(result, "Audio - closing device");
|
||||
}
|
||||
|
||||
void Platform_AudioSetFormat(Int32 handle, struct AudioFormat* format) {
|
||||
struct AudioContext* ctx = &Audio_Contexts[handle];
|
||||
struct AudioFormat* cur = &ctx->Format;
|
||||
|
||||
/* only recreate handle if we need to */
|
||||
if (AudioFormat_Eq(cur, format)) return;
|
||||
if (ctx->Handle) Platform_AudioFree(handle);
|
||||
|
||||
WAVEFORMATEX fmt = { 0 };
|
||||
fmt.nChannels = format->Channels;
|
||||
fmt.wFormatTag = WAVE_FORMAT_PCM;
|
||||
fmt.wBitsPerSample = format->BitsPerSample;
|
||||
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
|
||||
fmt.nSamplesPerSec = format->Frequency;
|
||||
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
|
||||
|
||||
if (waveOutGetNumDevs() == 0u) ErrorHandler_Fail("No audio devices found");
|
||||
ReturnCode result = waveOutOpen(&ctx->Handle, UInt32_MaxValue, &fmt, NULL, NULL, CALLBACK_NULL);
|
||||
ErrorHandler_CheckOrFail(result, "Audio - opening device");
|
||||
}
|
||||
|
||||
void Platform_AudioPlayAsync(Int32 handle, void* data, UInt32 dataSize) {
|
||||
struct AudioContext* ctx = &Audio_Contexts[handle];
|
||||
WAVEHDR* hdr = &ctx->Headers[0];
|
||||
Platform_MemSet(hdr, 0, sizeof(WAVEHDR));
|
||||
|
||||
hdr->lpData = data;
|
||||
hdr->dwBufferLength = dataSize;
|
||||
hdr->dwLoops = 1;
|
||||
ctx->PlayingAsync = true;
|
||||
|
||||
ReturnCode result = waveOutPrepareHeader(ctx->Handle, hdr, sizeof(WAVEHDR));
|
||||
ErrorHandler_CheckOrFail(result, "Audio - prepare header");
|
||||
result = waveOutWrite(ctx->Handle, hdr, sizeof(WAVEHDR));
|
||||
ErrorHandler_CheckOrFail(result, "Audio - write header");
|
||||
}
|
||||
|
||||
Int32 Platform_AudioNextFinishedAsync(Int32 handle) {
|
||||
struct AudioContext* ctx = &Audio_Contexts[handle];
|
||||
Int32 i;
|
||||
for (i = 0; i < ctx->NumBuffers; i++) {
|
||||
WAVEHDR* hdr = &ctx->Headers[i];
|
||||
if (!(hdr->dwFlags & WHDR_DONE)) continue;
|
||||
|
||||
if (hdr->dwFlags & WHDR_PREPARED) {
|
||||
ReturnCode result = waveOutUnprepareHeader(ctx->Handle, hdr, sizeof(WAVEHDR));
|
||||
ErrorHandler_CheckOrFail(result, "Audio - unprepare header");
|
||||
}
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Platform_AudioFinishedAsync(Int32 handle) {
|
||||
struct AudioContext* ctx = &Audio_Contexts[handle];
|
||||
if (!ctx->PlayingAsync) return true;
|
||||
Int32 index = Platform_AudioNextFinishedAsync(handle);
|
||||
|
||||
if (index >= 0) return false;
|
||||
ctx->PlayingAsync = false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user