From ca22cf15580293e223acebe8eaa1aee9373ea35a Mon Sep 17 00:00:00 2001 From: Firew0lf Date: Tue, 5 Jan 2016 19:41:25 +0100 Subject: [PATCH] =?UTF-8?q?Added=20ctr.mic,=20Added=20a=20function=20to=20?= =?UTF-8?q?get=20a=20=C2=B5s=20counter=20value.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Didn't test ctr.mic. --- source/audio.c | 50 ++++++++ source/ctr.c | 25 +++- source/mic.c | 304 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 377 insertions(+), 2 deletions(-) create mode 100644 source/mic.c diff --git a/source/audio.c b/source/audio.c index 6aa75b4..1f72900 100644 --- a/source/audio.c +++ b/source/audio.c @@ -242,6 +242,55 @@ static int audio_load(lua_State *L) { return 0; } +/*** +Load raw audio data from a string. +@function loadRaw +@tparam string data raw audio data +@tparam number rate sampling rate +@tparam string encoding audio encoding, can be `"PCM8"`, `"PCM16"` or `"ADPCM"` +@tparam[opt=1] number channels audio channels count +@treturn[1] audio the loaded audio object +@treturn[2] nil if a error happened +@treturn[2] string error message +*/ +static int audio_loadRaw(lua_State *L) { + size_t dataSize; + char* data = (char*)luaL_checklstring(L, 1, &dataSize); + float rate = luaL_checkinteger(L, 2); + const char* argEncoding = luaL_checkstring(L, 3); + u32 channels = luaL_optinteger(L, 4, 1); + + audio_userdata *audio = lua_newuserdata(L, sizeof(*audio)); + luaL_getmetatable(L, "LAudio"); + lua_setmetatable(L, -2); + + audio->type = TYPE_WAV; + audio->rate = rate; + audio->channels = channels; + + u8 sampleSize = 2; // default to 2 + if (strcmp(argEncoding, "PCM8")) { + audio->encoding = NDSP_ENCODING_PCM8; + sampleSize = 1; + } else if (strcmp(argEncoding, "PCM16")) { + audio->encoding = NDSP_ENCODING_PCM16; + } else if (strcmp(argEncoding, "ADPCM")) { + audio->encoding = NDSP_ENCODING_ADPCM; + } else { + lua_pushnil(L); + lua_pushstring(L, "Wrong format"); + return 2; + } + + audio->nsamples = dataSize/sampleSize; + audio->size = dataSize; + audio->data = data; + + audio->speed = 1.0; + + return 1; +} + /*** Check if audio is currently playing on a channel. @function playing @@ -817,6 +866,7 @@ static const struct luaL_Reg audio_object_methods[] = { // Library functions static const struct luaL_Reg audio_lib[] = { { "load", audio_load }, + { "loadRaw", audio_loadRaw }, { "playing", audio_playing }, { "mix", audio_mix }, { "interpolation", audio_interpolation }, diff --git a/source/ctr.c b/source/ctr.c index 43f15dc..06f7292 100644 --- a/source/ctr.c +++ b/source/ctr.c @@ -6,6 +6,7 @@ The `ctr` module. #include <3ds/types.h> #include <3ds/services/apt.h> #include <3ds/os.h> +#include <3ds/svc.h> #include #include @@ -106,6 +107,13 @@ The `ctr.apt` module. */ void load_apt_lib(lua_State *L); +/*** +The `ctr.mic` module. +@table mic +@see ctr.mic +*/ +void load_mic_lib(lua_State *L); + /*** Return whether or not the program should continue. @function run @@ -128,10 +136,22 @@ static int ctr_time(lua_State *L) { return 1; } +/*** +Return a number of microseconds based on the system ticks. +@function utime +@treturn number microseconds +*/ +static int ctr_utime(lua_State *L) { + lua_pushinteger(L, svcGetSystemTick()/268.123480); + + return 1; +} + // Functions static const struct luaL_Reg ctr_lib[] = { - { "run", ctr_run }, - { "time", ctr_time}, + { "run", ctr_run }, + { "time", ctr_time }, + { "utime", ctr_utime}, { NULL, NULL } }; @@ -150,6 +170,7 @@ struct { char *name; void (*load)(lua_State *L); void (*unload)(lua_State *L); } { "cam", load_cam_lib, NULL }, { "audio", load_audio_lib, unload_audio_lib }, { "apt", load_apt_lib, NULL }, + { "mic", load_mic_lib, NULL }, { NULL, NULL } }; diff --git a/source/mic.c b/source/mic.c new file mode 100644 index 0000000..ed9d308 --- /dev/null +++ b/source/mic.c @@ -0,0 +1,304 @@ +/*** +The `mic` module. +@module ctr.mic +@usage local mic = require("ctr.mic") +*/ + +#include <3ds/types.h> +#include <3ds/services/mic.h> + +#include +#include + +#include +#include + +u8* buff; +u32 bufferSize = 0; + +/*** +Initialize the mic module. +@function init +@tparam[opt=0x50000] number bufferSize size of the buffer (must be a multiple of 0x1000) +*/ +static int mic_init(lua_State *L) { + bufferSize = luaL_optinteger(L, 1, 0x50000); + + buff = memalign(0x1000, bufferSize); + if (buff == NULL) { + lua_pushnil(L); + lua_pushstring(L, "Couldn't allocate buffer"); + return 2; + } + Result ret = micInit(buff, bufferSize); + if (ret) { + free(buff); + lua_pushnil(L); + lua_pushinteger(L, ret); + return 2; + } + + lua_pushboolean(L, true); + return 1; +} + +/*** +Shutdown the mic module. +@function shutdown +*/ +static int mic_shutdown(lua_State *L) { + micExit(); + free(buff); + return 0; +} + +/*** +Start sampling from the mic. +@function startSampling +@tparam[opt="PCM8"] encoding encoding encoding of the data to record, can be `"PCM8"` or `"PCM16"` +@tparam[opt=8180] number rate sampling rate, can be `8180`, `10910`, `16360` or `32730` +@tparam[opt=false] boolean loop if true, loop back to the beginning of the buffer when the end is reached +@tparam[opt=bufferFreeSize-4] number size size of audio data to write to the buffer, can be reduced to fit in the buffer +@tparam[opt=false] boolean restart if `true`, start at position 0 in the buffer; if `false`, start after the last sample +*/ +static int mic_startSampling(lua_State *L) { + const char *encodingArg = luaL_optstring(L, 1, "PCM8"); + MICU_Encoding encoding = MICU_ENCODING_PCM8; + if (strcmp(encodingArg, "PCM16")) { + encoding = MICU_ENCODING_PCM16; + } + + u16 rateArg = luaL_optinteger(L, 2, 8180); + MICU_SampleRate rate = MICU_SAMPLE_RATE_8180; + switch (rateArg) { + case 10910: + rate = MICU_SAMPLE_RATE_10910; + case 16360: + rate = MICU_SAMPLE_RATE_16360; + case 32730: + rate = MICU_SAMPLE_RATE_32730; + } + + bool loop = false; + if (lua_isboolean(L, 3)) + loop = lua_toboolean(L, 3); + + + u32 currentSampleSize = micGetSampleDataSize(); + u32 size = luaL_optinteger(L, 4, bufferSize-currentSampleSize-4); + if (size > (bufferSize-currentSampleSize-4)) { + size = bufferSize-currentSampleSize-4; + } + + u32 offset = currentSampleSize; + if (lua_isboolean(L, 5) && lua_toboolean(L, 5)) // restart to 0 + offset = 0; + + MICU_StartSampling(encoding, rate, offset, size, loop); + + return 0; +} + +/*** +Stop sampling from the mic. +@function stopSampling +*/ +static int mic_stopSampling(lua_State *L) { + MICU_StopSampling(); + + return 0; +} + +/*** +Adjust the sampling rate. +@function adjustSampling +@tparam number rate sampling rate, can be `8180`, `10910`, `16360` or `32730` +*/ +static int mic_adjustSampling(lua_State *L) { + u16 rateArg = luaL_checkinteger(L, 1); + MICU_SampleRate rate = MICU_SAMPLE_RATE_8180; + switch (rateArg) { + case 10910: + rate = MICU_SAMPLE_RATE_10910; + case 16360: + rate = MICU_SAMPLE_RATE_16360; + case 32730: + rate = MICU_SAMPLE_RATE_32730; + } + + MICU_AdjustSampling(rate); + + return 0; +} + +/*** +Check whether the mic is sampling. +@function isSampling +@treturn boolean `true` if sampling +*/ +static int mic_isSampling(lua_State *L) { + bool sampling; + MICU_IsSampling(&sampling); + + lua_pushboolean(L, sampling); + return 1; +} + +/*** +Return a string containing the raw sampled audio data. +@function getData +@tparam[opt=true] boolean lastSampleOnly set to `true` to only get the last sample, and to `false` to get everything +@treturn string raw audio data +*/ +static int mic_getData(lua_State *L) { + bool last = false; + if (lua_isboolean(L, 1)) + last = lua_toboolean(L, 1); + + u32 offset = 0; + if (last) { + offset = micGetLastSampleOffset(); + } + u32 size = micGetSampleDataSize(); + + char* data = malloc(size-offset); + for (int i=offset;i