forked from libretro/libretro-lutro
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sound.c
117 lines (88 loc) · 2.79 KB
/
sound.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include "sound.h"
#include "lutro.h"
#include "audio.h"
#include "compat/strl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int lutro_sound_preload(lua_State *L)
{
static luaL_Reg snd_funcs[] = {
{ "newSoundData", snd_newSoundData },
{NULL, NULL}
};
lutro_ensure_global_table(L, "lutro");
luaL_newlib(L, snd_funcs);
lua_setfield(L, -2, "sound");
return 1;
}
void lutro_sound_init()
{
}
int snd_newSoundData(lua_State *L)
{
int n = lua_gettop(L);
if (n != 1)
return luaL_error(L, "lutro.sound.newSoundData requires 1 argument, %d given.", n);
const char* path = luaL_checkstring(L, 1);
AssetPathInfo asset;
lutro_assetPath_init(&asset, path);
snd_SoundData* self = (snd_SoundData*)lua_newuserdata(L, sizeof(snd_SoundData));
presaturate_buffer_desc bufdesc;
if (strstr(asset.ext, "ogg"))
{
dec_OggData oggData;
decOgg_init(&oggData, asset.fullpath);
self->numSamples = decOgg_sampleLength(&oggData);
self->numChannels = oggData.info->channels;
self->data = calloc(1, sizeof(mixer_presaturate_t) * self->numSamples * self->numChannels);
bufdesc.data = self->data;
bufdesc.channels = self->numChannels;
bufdesc.samplelen = self->numSamples;
decOgg_decode(&oggData, &bufdesc, 1.0f, false);
decOgg_destroy(&oggData);
}
if (strstr(asset.ext, "wav"))
{
dec_WavData wavData;
decWav_init(&wavData, asset.fullpath);
self->numSamples = wavData.head.Subchunk2Size / ((wavData.head.BitsPerSample/8) * wavData.head.NumChannels);
self->numChannels = wavData.head.NumChannels;
self->data = calloc(1, sizeof(mixer_presaturate_t) * self->numSamples * self->numChannels);
bufdesc.data = self->data;
bufdesc.channels = self->numChannels;
bufdesc.samplelen = self->numSamples;
decWav_decode(&wavData, &bufdesc, 1.0f, false);
decWav_destroy(&wavData);
}
if (luaL_newmetatable(L, "SoundData") != 0)
{
static luaL_Reg sndta_funcs[] = {
{ "type", sndta_type },
{ "__gc", sndta_gc },
{NULL, NULL}
};
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, sndta_gc);
lua_setfield( L, -2, "__gc" );
luaL_setfuncs(L, sndta_funcs, 0);
}
lua_setmetatable(L, -2);
return 1;
}
int sndta_type(lua_State *L)
{
snd_SoundData* self = (snd_SoundData*)luaL_checkudata(L, 1, "SoundData");
(void) self;
lua_pushstring(L, "SoundData");
return 1;
}
int sndta_gc(lua_State *L)
{
snd_SoundData* self = (snd_SoundData*)luaL_checkudata(L, 1, "SoundData");
free(self->data);
self->data = NULL;
// audio makes deep copies of this object when it preps it as a mixer source, so no mixer cleanup needed here.
return 0;
}