]> Chaos Git - corbenik/ctrulib.git/commitdiff
Rewrite MIC service code, clean up microphone example.
authorSteven Smith <Steveice10@gmail.com>
Sat, 7 Nov 2015 06:02:37 +0000 (22:02 -0800)
committerSteven Smith <Steveice10@gmail.com>
Sat, 7 Nov 2015 16:57:48 +0000 (08:57 -0800)
examples/audio/mic/source/main.c
libctru/include/3ds/services/mic.h
libctru/source/services/mic.c

index ca3ac65f08ba3c0a4231fb060f877519336c2cdd..95cb1afc038824eafd324cc6653fddd92b269697 100644 (file)
@@ -6,26 +6,37 @@
 
 int main()
 {
-       u8 *framebuf;
-       u32 *sharedmem = NULL, sharedmem_size = 0x30000;
-       u8 *audiobuf;
-       u32 audiobuf_size = 0x100000, audiobuf_pos = 0;
-       u8 control=0x40;
-       u32 audio_initialized = 0;
-
        gfxInitDefault();
        consoleInit(GFX_BOTTOM, NULL);
 
-       if(csndInit()==0)
+       bool initialized = true;
+
+       u32 micbuf_size = 0x30000;
+       u32 micbuf_pos = 0;
+       u8* micbuf = memalign(micbuf_size, 0x1000);
+
+       printf("Initializing CSND...\n");
+       if(R_FAILED(csndInit()))
        {
-               printf("Init success\n");
-               audio_initialized = 1;
-       }
+               initialized = false;
+               printf("Could not initialize CSND.\n");
+       } else printf("CSND initialized.\n");
+
+       printf("Initializing MIC...\n");
+       if(R_FAILED(micInit(micbuf, micbuf_size)))
+       {
+               initialized = false;
+               printf("Could not initialize MIC.\n");
+       } else printf("MIC initialized.\n");
+
+       u32 micbuf_datasize = micGetSampleDataSize();
 
-       sharedmem = (u32*)memalign(0x1000, sharedmem_size);
-       audiobuf = linearAlloc(audiobuf_size);
+       u32 audiobuf_size = 0x100000;
+       u32 audiobuf_pos = 0;
+       u8* audiobuf = linearAlloc(audiobuf_size);
 
-       MIC_Initialize(sharedmem, sharedmem_size, control, 0, 3, 1, 1);//See mic.h.
+       if(initialized) printf("Hold A to record, release to play.\n");
+       printf("Press START to exit.\n");
 
        while(aptMainLoop())
        {
@@ -36,45 +47,42 @@ int main()
                if (kDown & KEY_START)
                        break; // break in order to return to hbmenu
 
-               if(audio_initialized)
+               if(initialized)
                {
-                       framebuf = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
-
                        if(kDown & KEY_A)
                        {
                                audiobuf_pos = 0;
-                               printf("Stopping audio playback\n");
-                               CSND_SetPlayState(0x8, 0);//Stop audio playback.
-                               CSND_UpdateInfo(0);
+                               micbuf_pos = 0;
 
-                               MIC_SetRecording(1);
+                               printf("Stopping audio playback...\n");
+                               CSND_SetPlayState(0x8, 0);
+                               if(R_FAILED(CSND_UpdateInfo(0))) printf("Failed to stop audio playback.\n");
 
-                               memset(framebuf, 0x20, 0x46500);
-                               printf("Now recording\n");
+                               printf("Starting sampling...\n");
+                               if(R_SUCCEEDED(MICU_SetPower(true)) && R_SUCCEEDED(MICU_StartSampling(MICU_ENCODING_PCM16_SIGNED, MICU_SAMPLE_RATE_16360, 0, micbuf_datasize, true))) printf("Now recording.\n");
+                               else printf("Failed to start sampling.\n");
                        }
 
                        if((hidKeysHeld() & KEY_A) && audiobuf_pos < audiobuf_size)
                        {
-                               audiobuf_pos+= MIC_ReadAudioData(&audiobuf[audiobuf_pos], audiobuf_size-audiobuf_pos, 1);
-                               if(audiobuf_pos > audiobuf_size)audiobuf_pos = audiobuf_size;
-
-                               memset(framebuf, 0x60, 0x46500);
+                               u32 micbuf_readpos = micbuf_pos;
+                               micbuf_pos = micGetLastSampleOffset();
+                               while(audiobuf_pos < audiobuf_size && micbuf_readpos != micbuf_pos)
+                               {
+                                       audiobuf[audiobuf_pos] = micbuf[micbuf_readpos];
+                                       audiobuf_pos++;
+                                       micbuf_readpos = (micbuf_readpos + 1) % micbuf_datasize;
+                               }
                        }
 
                        if(hidKeysUp() & KEY_A)
                        {
-                               printf("Playing the recorded sample\n");
-                               MIC_SetRecording(0);
-                               GSPGPU_FlushDataCache(NULL, audiobuf, audiobuf_pos);
-                               csndPlaySound(0x8, SOUND_ONE_SHOT | SOUND_FORMAT_16BIT, 16000, 1.0, 0.0, (u32*)audiobuf, NULL, audiobuf_pos);
-
-                               memset(framebuf, 0xe0, 0x46500);
-
-                               gfxFlushBuffers();
-                               gfxSwapBuffers();
+                               printf("Stoping sampling...\n");
+                               if(R_FAILED(MICU_StopSampling()) || R_FAILED(MICU_SetPower(false))) printf("Failed to stop sampling.\n");
 
-                               framebuf = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
-                               memset(framebuf, 0xe0, 0x46500);
+                               printf("Starting audio playback...\n");
+                               if(R_SUCCEEDED(GSPGPU_FlushDataCache(audiobuf, audiobuf_pos)) && R_SUCCEEDED(csndPlaySound(0x8, SOUND_ONE_SHOT | SOUND_FORMAT_16BIT, 16360, 1.0, 0.0, (u32*)audiobuf, NULL, audiobuf_pos))) printf("Now playing.\n");
+                               else printf("Failed to start playback.\n");
                        }
                }
 
@@ -82,13 +90,12 @@ int main()
                gfxSwapBuffers();
        }
 
-       MIC_Shutdown();
-
-       if(audio_initialized)csndExit();
-
-       free(sharedmem);
        linearFree(audiobuf);
 
+       micExit();
+       free(micbuf);
+
+       csndExit();
        gfxExit();
        return 0;
 }
index 8efd0320955f8dcdbe85755fd609a011410417ae..609f759fc3a2a83c70fd9f69ba8aa3bf0e49cf8b 100644 (file)
  */
 #pragma once
 
-//See also: http://3dbrew.org/wiki/MIC_Services
+/// Microphone audio encodings.
+typedef enum
+{
+       MICU_ENCODING_PCM8 = 0,         ///< Unsigned 8-bit PCM.
+       MICU_ENCODING_PCM16 = 1,        ///< Unsigned 16-bit PCM.
+       MICU_ENCODING_PCM8_SIGNED = 2,  ///< Signed 8-bit PCM.
+       MICU_ENCODING_PCM16_SIGNED = 3, ///< Signed 16-bit PCM.
+} MICU_Encoding;
+
+/// Microphone audio sampling rates.
+typedef enum
+{
+       MICU_SAMPLE_RATE_32730 = 0, ///< 32730 Hz
+       MICU_SAMPLE_RATE_16360 = 1, ///< 16360 Hz
+       MICU_SAMPLE_RATE_10910 = 2, ///< 10910 Hz
+       MICU_SAMPLE_RATE_8180 =  3, ///< 8180 Hz
+} MICU_SampleRate;
 
 /**
  * @brief Initializes MIC.
- * @param sharedmem Shared memory block to use. Must be 0x1000-bytes aligned.
- * @param sharedmem_size Size of the shared memory block to use. (audiodata size + 4, aligned to 0x1000-bytes)
- * @param control Control value. Bits 0-6 = Amplification.
- * @param unk0 Unknown. Typically 3.
- * @param unk1 Unknown. Typically 1.
- * @param unk2 Unknown. Typically 1.
+ * @param size Shared memory buffer to write audio data to. Must be aligned to 0x1000 bytes.
+ * @param handle Size of the shared memory buffer.
  */
-Result MIC_Initialize(u32 *sharedmem, u32 sharedmem_size, u8 control, u8 recording, u8 unk0, u8 unk1, u8 unk2);
+Result micInit(u8* buffer, u32 bufferSize);
 
-/// Shuts down MIC.
-Result MIC_Shutdown(void);
+/// Exits MIC.
+void micExit(void);
 
 /**
- * @brief Gets the current shared memory offset.
- * @return The current shared memory offset.
+ * @brief Gets the size of the sample data area within the shared memory buffer.
+ * @return The sample data's size.
  */
-u32 MIC_GetSharedMemOffsetValue(void);
+u32 micGetSampleDataSize(void);
 
 /**
- * @brief Reads MIC audio data.
- * @param outbuf Buffer to write audio data to.
- * @param readsize Size of the buffer to write to.
- * @param waitforevent Whether to wait for the MIC service to signal that audio data is ready. (non-zero = wait)
- * @return Actual number of bytes read.
+ * @brief Gets the offset within the shared memory buffer of the last sample written.
+ * @return The last sample's offset.
  */
-u32 MIC_ReadAudioData(u8 *outbuf, u32 readsize, u32 waitforevent);
+u32 micGetLastSampleOffset(void);
 
 /**
- * @brief Maps MIC's shared memory.
- * @param handle Handle of the shared memory.
+ * @brief Maps MIC shared memory.
  * @param size Size of the shared memory.
+ * @param handle Handle of the shared memory.
  */
-Result MIC_MapSharedMem(Handle handle, u32 size);
+Result MICU_MapSharedMem(u32 size, Handle handle);
 
-/// Unmaps MIC's shardd memory.
-Result MIC_UnmapSharedMem(void);
+/// Unmaps MIC shared memory.
+Result MICU_UnmapSharedMem(void);
 
 /**
- * @brief Initializes MIC.
- * @param unk0 Unknown.
- * @param unk1 Unknown.
- * @param sharedmem_baseoffset Base offset of shared memory.
- * @param sharedmem_endoffset End offset of shared memory.
- * @param unk2 Unknown.
+ * @brief Begins sampling microphone input.
+ * @param encoding Encoding of outputted audio.
+ * @param sampleRate Sample rate of outputted audio.
+ * @param sharedMemAudioOffset Offset to write audio data to in the shared memory buffer.
+ * @param sharedMemAudioSize Size of audio data to write to the shared memory buffer. This should be at most "bufferSize - 4".
+ * @param loop Whether to loop back to the beginning of the buffer when the end is reached.
  */
-Result MIC_cmd3_Initialize(u8 unk0, u8 unk1, u32 sharedmem_baseoffset, u32 sharedmem_endoffset, u8 unk2);
+Result MICU_StartSampling(MICU_Encoding encoding, MICU_SampleRate sampleRate, u32 offset, u32 size, bool loop);
 
-/// Unknown MIC command.
-Result MIC_cmd5(void);
+/**
+ * @brief Adjusts the configuration of the current sampling session.
+ * @param sampleRate Sample rate of outputted audio.
+ */
+Result MICU_AdjustSampling(MICU_SampleRate sampleRate);
+
+/// Stops sampling microphone input.
+Result MICU_StopSampling(void);
 
 /**
- * @brief Gets CNT bit 15 from MIC.
- * @param out Pointer to output the bit to.
+ * @brief Gets whether microphone input is currently being sampled.
+ * @param sampling Pointer to output the sampling state to.
  */
-Result MIC_GetCNTBit15(u8 *out);
+Result MICU_IsSampling(bool* sampling);
 
 /**
- * @brief Gets the event handle signaled by MIC when data is ready.
+ * @brief Gets an event handle triggered when the shared memory buffer is full.
  * @param handle Pointer to output the event handle to.
  */
-Result MIC_GetEventHandle(Handle *handle);
+Result MICU_GetEventHandle(Handle* handle);
+
+/**
+ * @brief Sets the microphone's gain.
+ * @param gain Gain to set.
+ */
+Result MICU_SetGain(u8 gain);
 
 /**
- * Sets the control value.
- * @note Bits 0-6 = Amplification.
- * @param value Control value to set.
+ * @brief Gets the microphone's gain.
+ * @param gain Pointer to output the current gain to.
  */
-Result MIC_SetControl(u8 value);
+Result MICU_GetGain(u8* gain);
 
 /**
- * Gets the control value.
- * @note Bits 0-6 = Amplification.
- * @param value Pointer to output the control value to.
+ * @brief Sets whether the microphone is powered on.
+ * @param power Whether the microphone is powered on.
  */
-Result MIC_GetControl(u8 *value);
+Result MICU_SetPower(bool power);
 
 /**
- * Sets whether the microphone is recording.
- * @param value Whether the microphone is recording.
+ * @brief Gets whether the microphone is powered on.
+ * @param power Pointer to output the power state to.
  */
-Result MIC_SetRecording(u8 value);
+Result MICU_GetPower(bool* power);
 
 /**
- * Gets whether the microphone is recording.
- * @param value Pointer to output whether the microphone is recording to.
+ * @brief Sets whether to clamp microphone input.
+ * @param clamp Whether to clamp microphone input.
  */
-Result MIC_IsRecoding(u8 *value);
+Result MICU_SetClamp(bool clamp);
 
+/**
+ * @brief Gets whether to clamp microphone input.
+ * @param clamp Pointer to output the clamp state to.
+ */
+Result MICU_GetClamp(bool* clamp);
+
+/**
+ * @brief Sets whether to allow sampling when the shell is closed.
+ * @param allowShellClosed Whether to allow sampling when the shell is closed.
+ */
+Result MICU_SetAllowShellClosed(bool allowShellClosed);
index 17432804d8930cd7cf331226809c50563ba75984..9458a6ba6bc5165648940c3714e8d893a4211116 100644 (file)
 #include <stdlib.h>
-#include <string.h>
 #include <3ds/types.h>
 #include <3ds/svc.h>
 #include <3ds/srv.h>
 #include <3ds/services/mic.h>
 #include <3ds/ipc.h>
+#include <3ds/synchronization.h>
+#include <3ds/result.h>
 
-//See also: http://3dbrew.org/wiki/MIC_Services
+static Handle micHandle;
+static int micRefCount;
 
-Handle MIC_handle;
+static u8* micSharedMem;
+static u32 micSharedMemSize;
+static Handle micSharedMemHandle;
 
-static u8 *MIC_sharedmem;
-static u32 MIC_sharedmem_size;
-static u32 *MIC_sharedmem_offsetfield, MIC_sharedmem_offsetfield_location;
-static Handle MIC_sharedmem_handle;
-static Handle MIC_event;
-
-static u32 MIC_prev_endpos, MIC_cur_endpos;
-
-Result MIC_Initialize(u32 *sharedmem, u32 sharedmem_size, u8 control, u8 recording, u8 unk0, u8 unk1, u8 unk2)
+Result micInit(u8* buffer, u32 bufferSize)
 {
-       Result ret=0;
-
-       MIC_sharedmem = (u8*)sharedmem;
-       MIC_sharedmem_size = sharedmem_size;
-       MIC_sharedmem_offsetfield_location = MIC_sharedmem_size - 4;
-       MIC_sharedmem_offsetfield = (u32*)&MIC_sharedmem[MIC_sharedmem_offsetfield_location];
-       MIC_event = 0;
-       MIC_prev_endpos = 0;
-       MIC_cur_endpos = 0;
-
-       ret = srvGetServiceHandle(&MIC_handle, "mic:u");
-       if(ret!=0)return ret;
+       Result ret = 0;
 
-       ret = svcCreateMemoryBlock(&MIC_sharedmem_handle, (u32)MIC_sharedmem, MIC_sharedmem_size, 3, 3);
-       if(ret!=0)return ret;
+       if (AtomicPostIncrement(&micRefCount)) return 0;
 
-       ret = MIC_SetControl(control);
-       if(ret!=0)return ret;
+       ret = srvGetServiceHandle(&micHandle, "mic:u");
+       if (R_FAILED(ret)) goto end;
 
-       ret = MIC_MapSharedMem(MIC_sharedmem_handle, sharedmem_size);
-       if(ret!=0)return ret;
+       micSharedMem = buffer;
+       micSharedMemSize = bufferSize;
 
-       ret = MIC_SetRecording(recording);
-       if(ret!=0)return ret;
+       ret = svcCreateMemoryBlock(&micSharedMemHandle, (u32) micSharedMem, micSharedMemSize, MEMPERM_READ | MEMPERM_WRITE, MEMPERM_READ | MEMPERM_WRITE);
+       if (R_FAILED(ret)) goto end;
 
-       ret = MIC_cmd3_Initialize(unk0, unk1, 0, MIC_sharedmem_size-4, unk2);
-       if(ret!=0)return ret;
-
-       ret = MIC_GetEventHandle(&MIC_event);
-       if(ret!=0)return ret;
-       svcClearEvent(MIC_event);
-
-       return 0;
+       ret = MICU_MapSharedMem(micSharedMemSize, micSharedMemHandle);
+end:
+       if (R_FAILED(ret)) micExit();
+       return ret;
 }
 
-Result MIC_Shutdown(void)
+void micExit(void)
 {
-       Result ret=0;
-
-       MIC_cmd5();
-       MIC_SetRecording(0);
+       if (AtomicDecrement(&micRefCount)) return;
 
-       ret = MIC_UnmapSharedMem();
-       if(ret!=0)return ret;
-
-       MIC_cmd5();
-
-       ret = svcCloseHandle(MIC_sharedmem_handle);
-       if(ret!=0)return ret;
-
-       ret = svcCloseHandle(MIC_event);
-       if(ret!=0)return ret;
-
-       ret = svcCloseHandle(MIC_handle);
-       if(ret!=0)return ret;
+       if (micSharedMemHandle)
+       {
+               MICU_UnmapSharedMem();
+               svcCloseHandle(micSharedMemHandle);
+               micSharedMemHandle = 0;
+       }
 
-       MIC_sharedmem_offsetfield = NULL;
-       MIC_sharedmem = NULL;
-       MIC_sharedmem_size = 0;
-       MIC_handle = 0;
-       MIC_event = 0;
+       if(micHandle)
+       {
+               svcCloseHandle(micHandle);
+               micHandle = 0;
+       }
 
-       return 0;
+       micSharedMem = NULL;
+       micSharedMemSize = 0;
 }
 
-u32 MIC_GetSharedMemOffsetValue(void)
+u32 micGetSampleDataSize(void)
 {
-       u32 pos = 0;
-
-       if(MIC_sharedmem_offsetfield==NULL)return pos;
-       pos = *MIC_sharedmem_offsetfield;
-       if(pos > MIC_sharedmem_offsetfield_location)pos = MIC_sharedmem_offsetfield_location;
-
-       return pos;
+       return micSharedMemSize - 4;
 }
 
-u32 MIC_ReadAudioData(u8 *outbuf, u32 readsize, u32 waitforevent)
+u32 micGetLastSampleOffset(void)
 {
-       u32 pos = 0, bufpos = 0;
-       
-       if(waitforevent)
-       {
-               svcClearEvent(MIC_event);
-               svcWaitSynchronization(MIC_event, U64_MAX);
-       }
-
-       MIC_prev_endpos = MIC_cur_endpos;
-       MIC_cur_endpos = MIC_GetSharedMemOffsetValue();
-       pos = MIC_prev_endpos;
-
-       while(pos != MIC_cur_endpos)
-       {
-               if(pos >= MIC_sharedmem_offsetfield_location)pos = 0;
-               if(bufpos>=readsize)break;
-
-               outbuf[bufpos] = MIC_sharedmem[pos];
-               bufpos++;
-               pos++;
-       }
-
-       return bufpos;
+       if(micSharedMem) return *(u32*) &micSharedMem[micGetSampleDataSize()];
+       return 0;
 }
 
-Result MIC_MapSharedMem(Handle handle, u32 size)
+Result MICU_MapSharedMem(u32 size, Handle handle)
 {
-       Result ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
        cmdbuf[0] = IPC_MakeHeader(0x1,1,2); // 0x10042
        cmdbuf[1] = size;
        cmdbuf[2] = IPC_Desc_SharedHandles(1);
        cmdbuf[3] = handle;
 
-       if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret;
-
-       return (Result)cmdbuf[1];
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       return cmdbuf[1];
 }
 
-Result MIC_UnmapSharedMem(void)
+Result MICU_UnmapSharedMem(void)
 {
-       Result ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
        cmdbuf[0] = IPC_MakeHeader(0x2,0,0); // 0x20000
 
-       if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret;
-
-       return (Result)cmdbuf[1];
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       return cmdbuf[1];
 }
 
-Result MIC_cmd3_Initialize(u8 unk0, u8 unk1, u32 sharedmem_baseoffset, u32 sharedmem_endoffset, u8 unk2)
+Result MICU_StartSampling(MICU_Encoding encoding, MICU_SampleRate sampleRate, u32 offset, u32 size, bool loop)
 {
-       Result ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
        cmdbuf[0] = IPC_MakeHeader(0x3,5,0); // 0x30140
-       cmdbuf[1] = unk0;
-       cmdbuf[2] = unk1;
-       cmdbuf[3] = sharedmem_baseoffset;
-       cmdbuf[4] = sharedmem_endoffset;
-       cmdbuf[5] = unk2;
+       cmdbuf[1] = encoding;
+       cmdbuf[2] = sampleRate;
+       cmdbuf[3] = offset;
+       cmdbuf[4] = size;
+       cmdbuf[5] = loop;
+
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       return cmdbuf[1];
+}
 
-       if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret;
+Result MICU_AdjustSampling(MICU_SampleRate sampleRate)
+{
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
+       cmdbuf[0] = IPC_MakeHeader(0x4,1,0); // 0x40040
+       cmdbuf[1] = sampleRate;
 
-       return (Result)cmdbuf[1];
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       return cmdbuf[1];
 }
 
-Result MIC_cmd5(void)
+Result MICU_StopSampling(void)
 {
-       Result ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
        cmdbuf[0] = IPC_MakeHeader(0x5,0,0); // 0x50000
 
-       if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret;
-
-       return (Result)cmdbuf[1];
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       return cmdbuf[1];
 }
 
-Result MIC_GetCNTBit15(u8 *out)
+Result MICU_IsSampling(bool* sampling)
 {
-       Result ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
        cmdbuf[0] = IPC_MakeHeader(0x6,0,0); // 0x60000
 
-       if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret;
-
-       if(out)*out = cmdbuf[2];
-
-       return (Result)cmdbuf[1];
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       if (sampling) *sampling = cmdbuf[2] & 0xFF;
+       return cmdbuf[1];
 }
 
-Result MIC_GetEventHandle(Handle *handle)
+Result MICU_GetEventHandle(Handle* handle)
 {
-       Result ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
-       if(MIC_event)
-       {
-               *handle = MIC_event;
-               return 0;
-       }
-
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
        cmdbuf[0] = IPC_MakeHeader(0x7,0,0); // 0x70000
 
-       if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret;
-
-       if(handle)*handle = cmdbuf[3];
-
-       return (Result)cmdbuf[1];
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       if (handle) *handle = cmdbuf[3];
+       return cmdbuf[1];
 }
 
-Result MIC_SetControl(u8 value)
+Result MICU_SetGain(u8 gain)
 {
-       Result ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
        cmdbuf[0] = IPC_MakeHeader(0x8,1,0); // 0x80040
-       cmdbuf[1] = value;
+       cmdbuf[1] = gain;
 
-       if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret;
-
-       return (Result)cmdbuf[1];
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       return cmdbuf[1];
 }
 
-Result MIC_GetControl(u8 *value)
+Result MICU_GetGain(u8* gain)
 {
-       Result ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
        cmdbuf[0] = IPC_MakeHeader(0x9,0,0); // 0x90000
 
-       if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret;
-
-       if(value)*value = cmdbuf[2];
-
-       return (Result)cmdbuf[1];
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       if (gain) *gain = cmdbuf[2] & 0xFF;
+       return cmdbuf[1];
 }
 
-Result MIC_SetRecording(u8 value)
+Result MICU_SetPower(bool power)
 {
-       Result ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
        cmdbuf[0] = IPC_MakeHeader(0xA,1,0); // 0xA0040
-       cmdbuf[1] = value;
+       cmdbuf[1] = power;
 
-       if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret;
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       return cmdbuf[1];
+}
 
-       if(value==1)MIC_cur_endpos = MIC_GetSharedMemOffsetValue();
+Result MICU_GetPower(bool* power)
+{
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
+       cmdbuf[0] = IPC_MakeHeader(0xB,0,0); // 0xB0000
 
-       return (Result)cmdbuf[1];
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       if (power) *power = cmdbuf[2] & 0xFF;
+       return cmdbuf[1];
 }
 
-Result MIC_IsRecoding(u8 *value)
+Result MICU_SetClamp(bool clamp)
 {
-       Result ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
+       cmdbuf[0] = IPC_MakeHeader(0xD,1,0); // 0xD0040
+       cmdbuf[1] = clamp;
 
-       cmdbuf[0] = IPC_MakeHeader(0xB,0,0); // 0xB0000
-
-       if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret;
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       return cmdbuf[1];
+}
 
-       if(value)*value = cmdbuf[2];
+Result MICU_GetClamp(bool* clamp)
+{
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
+       cmdbuf[0] = IPC_MakeHeader(0xE,0,0); // 0xE0000
 
-       return (Result)cmdbuf[1];
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       if (clamp) *clamp = cmdbuf[2] & 0xFF;
+       return cmdbuf[1];
 }
 
+Result MICU_SetAllowShellClosed(bool allowShellClosed)
+{
+       Result ret = 0;
+       u32* cmdbuf = getThreadCommandBuffer();
+       cmdbuf[0] = IPC_MakeHeader(0xF,1,0); // 0xF0040
+       cmdbuf[1] = allowShellClosed;
+
+       if (R_FAILED(ret = svcSendSyncRequest(micHandle))) return ret;
+       return cmdbuf[1];
+}