Advertisement
Guest User

Untitled

a guest
Mar 29th, 2015
289
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 46.28 KB | None | 0 0
  1. /*----------------------------------------------------------------------------------------------------------------------#
  2. #-----------------------------------------------------------------------------------------------------------------------#
  3. #------  This File is Part Of : ----------------------------------------------------------------------------------------#
  4. #------- _  -------------------  ______   _   --------------------------------------------------------------------------#
  5. #------ | | ------------------- (_____ \ | |  --------------------------------------------------------------------------#
  6. #------ | | ---  _   _   ____    _____) )| |  ____  _   _   ____   ____   ----------------------------------------------#
  7. #------ | | --- | | | | / _  |  |  ____/ | | / _  || | | | / _  ) / ___)  ----------------------------------------------#
  8. #------ | |_____| |_| |( ( | |  | |      | |( ( | || |_| |( (/ / | |  --------------------------------------------------#
  9. #------ |_______)\____| \_||_|  |_|      |_| \_||_| \__  | \____)|_|  --------------------------------------------------#
  10. #------------------------------------------------- (____/  -------------------------------------------------------------#
  11. #------------------------   ______   _   -------------------------------------------------------------------------------#
  12. #------------------------  (_____ \ | |  -------------------------------------------------------------------------------#
  13. #------------------------   _____) )| | _   _   ___   ------------------------------------------------------------------#
  14. #------------------------  |  ____/ | || | | | /___)  ------------------------------------------------------------------#
  15. #------------------------  | |      | || |_| ||___ |  ------------------------------------------------------------------#
  16. #------------------------  |_|      |_| \____|(___/   ------------------------------------------------------------------#
  17. #-----------------------------------------------------------------------------------------------------------------------#
  18. #-----------------------------------------------------------------------------------------------------------------------#
  19. #- Licensed under the GPL License --------------------------------------------------------------------------------------#
  20. #-----------------------------------------------------------------------------------------------------------------------#
  21. #- Copyright (c) Nanni <lpp.nanni@gmail.com> ---------------------------------------------------------------------------#
  22. #- Copyright (c) Rinnegatamante <rinnegatamante@gmail.com> -------------------------------------------------------------#
  23. #-----------------------------------------------------------------------------------------------------------------------#
  24. #-----------------------------------------------------------------------------------------------------------------------#
  25. #- Credits : -----------------------------------------------------------------------------------------------------------#
  26. #-----------------------------------------------------------------------------------------------------------------------#
  27. #- Smealum for ctrulib and ftpony src ----------------------------------------------------------------------------------#
  28. #- StapleButter for debug font -----------------------------------------------------------------------------------------#
  29. #- Lode Vandevenne for lodepng -----------------------------------------------------------------------------------------#
  30. #- Jean-loup Gailly and Mark Adler for zlib ----------------------------------------------------------------------------#
  31. #- Special thanks to Aurelio for testing, bug-fixing and various help with codes and implementations -------------------#
  32. #-----------------------------------------------------------------------------------------------------------------------*/
  33.  
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <unistd.h>
  37. #include <malloc.h>
  38. #include <3ds.h>
  39. #include "include/luaplayer.h"
  40. #include "include/graphics/Graphics.h"
  41. #include "include/luaAudio.h"
  42. #include "include/ogg/ogg.h"
  43. #include "include/ogg/codec.h"
  44. #include "include/ogg/vorbisfile.h"
  45.  
  46. struct wav{
  47. u32 magic;
  48. u32 samplerate;
  49. u16 bytepersample;
  50. u8* audiobuf;
  51. u8* audiobuf2;
  52. u32 size;
  53. u32 mem_size;
  54. Handle sourceFile;
  55. u32 startRead;
  56. char author[256];
  57. char title[256];
  58. u32 moltiplier;
  59. u64 tick;
  60. bool isPlaying;
  61. u32 ch;
  62. u32 ch2;
  63. bool streamLoop;
  64. bool big_endian;
  65. u8 encoding;
  66. u32* thread;
  67. };
  68.  
  69. volatile bool closeStream = false;
  70. Handle updateStream;
  71. Handle streamThread;
  72.  
  73. int STREAM_MAX_ALLOC = 524288;
  74.  
  75. void streamOGG(void* arg){
  76.     while(1) {
  77.         svcWaitSynchronization(updateStream, U64_MAX);
  78.         svcClearEvent(updateStream);
  79.         wav* src = (wav*)arg;
  80.         u32 bytesRead;
  81.         u32 control;
  82.        
  83.         while(1){
  84.             if(closeStream){
  85.                 closeStream = false;
  86.                 svcExitThread();
  87.             }
  88.            
  89.             // Initializing libogg and vorbisfile
  90.             int eof=0;
  91.             static int current_section = src->startRead;
  92.    
  93.             u32 control;
  94.             u32 total = src->size;
  95.             u32 block_size = src->mem_size / 2;
  96.             if (src->audiobuf2 == NULL) control = src->samplerate * 2 * ((osGetTime() - src->tick) / 1000);
  97.             else{
  98.                 control = src->samplerate * 4 * ((osGetTime() - src->tick) / 1000);
  99.                 total = total * 2;
  100.             }
  101.             if ((control >= total) && (src->isPlaying)){
  102.                 CSND_setchannel_playbackstate(src->ch, 0);
  103.                 if (src->audiobuf2 != NULL) CSND_setchannel_playbackstate(src->ch2, 0);
  104.                 CSND_sharedmemtype0_cmdupdatestate(0);
  105.                 src->moltiplier = 1;
  106.                 ov_raw_seek((OggVorbis_File*)src->sourceFile,0);
  107.                 if (src->audiobuf2 == NULL){
  108.                     char pcmout[4096];
  109.                     int i = 0;
  110.                     while(!eof){
  111.                         long ret=ov_read((OggVorbis_File*)src->sourceFile,pcmout,sizeof(pcmout),0,2,1,&current_section);
  112.                         if (ret == 0) {
  113.                             eof=1;
  114.                         } else {
  115.                             memcpy(&src->audiobuf[i],pcmout,ret);
  116.                             i = i + ret;
  117.                             if (i >= (src->mem_size)) break;
  118.                         }
  119.                     }
  120.                 }else{
  121.                     u8* tmp_buf = (u8*)linearAlloc(src->mem_size);
  122.                     char pcmout[2048];
  123.                     int i = 0;
  124.                     while(!eof){
  125.                         long ret=ov_read((OggVorbis_File*)src->sourceFile,pcmout,sizeof(pcmout),0,2,1,&current_section);
  126.                         if (ret == 0) {
  127.                             eof=1;
  128.                         } else {
  129.                             memcpy(&tmp_buf[i],pcmout,ret);
  130.                             i = i + ret;
  131.                             if (i >= src->mem_size) break; 
  132.                         }
  133.                     }
  134.        
  135.                     // Separating left and right channels
  136.                     int z;
  137.                     int j=0;
  138.                     for (z=0; z < src->mem_size; z=z+4){
  139.                         src->audiobuf[j] = tmp_buf[z];
  140.                         src->audiobuf[j+1] = tmp_buf[z+1];
  141.                         src->audiobuf2[j] = tmp_buf[z+2];
  142.                         src->audiobuf2[j+1] = tmp_buf[z+3];
  143.                         j=j+2;
  144.                     }
  145.                     linearFree(tmp_buf);
  146.                 }
  147.                 if (!src->streamLoop){
  148.                     src->isPlaying = false;
  149.                     src->tick = (osGetTime()-src->tick);
  150.                 }else{
  151.                     src->tick = osGetTime();
  152.                     CSND_setchannel_playbackstate(src->ch, 1);
  153.                     if (src->audiobuf2 != NULL) CSND_setchannel_playbackstate(src->ch2, 1);
  154.                     CSND_sharedmemtype0_cmdupdatestate(0);
  155.                 }
  156.             }else if ((control > (block_size * src->moltiplier)) && (src->isPlaying)){
  157.                 if ((src->moltiplier % 2) == 1){
  158.                     //Update and flush first half-buffer
  159.                     if (src->audiobuf2 == NULL){ //Mono file
  160.                         char pcmout[4096];
  161.                         int i = 0;
  162.                         while(!eof){
  163.                             long ret=ov_read((OggVorbis_File*)src->sourceFile,pcmout,sizeof(pcmout),0,2,1,&current_section);
  164.                             if (ret == 0) {
  165.                                 eof=1;
  166.                             } else {
  167.                                 memcpy(&src->audiobuf[i],pcmout,ret);
  168.                                 i = i + ret;
  169.                                 if (i >= (block_size)) break;
  170.                             }
  171.                         }
  172.                     }else{ //Stereo file
  173.                         u8* tmp_buf = (u8*)linearAlloc(block_size);
  174.                         char pcmout[2048];
  175.                         int i = 0;
  176.                         while(!eof){
  177.                             long ret=ov_read((OggVorbis_File*)src->sourceFile,pcmout,sizeof(pcmout),0,2,1,&current_section);
  178.                             if (ret == 0) {
  179.                                 eof=1;
  180.                             } else {
  181.                                 memcpy(&tmp_buf[i],pcmout,ret);
  182.                                 i = i + ret;
  183.                                 if (i >= (block_size)) break;
  184.                             }
  185.                         }
  186.                
  187.                         // Separating left and right channels
  188.                         int z;
  189.                         int j=0;
  190.                         for (z=0; z < (block_size); z=z+4){
  191.                             src->audiobuf[j] = tmp_buf[z];
  192.                             src->audiobuf[j+1] = tmp_buf[z+1];
  193.                             src->audiobuf2[j] = tmp_buf[z+2];
  194.                             src->audiobuf2[j+1] = tmp_buf[z+3];
  195.                             j=j+2;
  196.                         }
  197.                         linearFree(tmp_buf);
  198.                
  199.                     }
  200.                     src->moltiplier = src->moltiplier + 1;
  201.                 }else{
  202.                     //Update and flush second half-buffer
  203.                     if (src->audiobuf2 == NULL){ //Mono file
  204.                         char pcmout[4096];
  205.                         int i = 0;
  206.                         while(!eof){
  207.                             long ret=ov_read((OggVorbis_File*)src->sourceFile,pcmout,sizeof(pcmout),0,2,1,&current_section);
  208.                             if (ret == 0) {
  209.                                 eof=1;
  210.                             } else {
  211.                                 memcpy(&src->audiobuf[i+block_size],pcmout,ret);
  212.                                 i = i + ret;
  213.                                 if (i >= block_size) break;
  214.                             }
  215.                         }
  216.                     }else{ //Stereo file
  217.                         u8* tmp_buf = (u8*)linearAlloc(block_size);
  218.                         char pcmout[2048];
  219.                         int i = 0;
  220.                         while(!eof){
  221.                             long ret=ov_read((OggVorbis_File*)src->sourceFile,pcmout,sizeof(pcmout),0,2,1,&current_section);
  222.                             if (ret == 0) {
  223.                                 eof=1;
  224.                             } else {
  225.                                 memcpy(&tmp_buf[i],pcmout,ret);
  226.                                 i = i + ret;
  227.                                 if (i >= (block_size)) break;
  228.                             }
  229.                         }
  230.                
  231.                         // Separating left and right channels
  232.                         int z;
  233.                         int j=block_size/2;
  234.                         for (z=0; z < block_size; z=z+4){
  235.                             src->audiobuf[j] = tmp_buf[z];
  236.                             src->audiobuf[j+1] = tmp_buf[z+1];
  237.                             src->audiobuf2[j] = tmp_buf[z+2];
  238.                             src->audiobuf2[j+1] = tmp_buf[z+3];
  239.                             j=j+2;
  240.                         }
  241.                         linearFree(tmp_buf);
  242.                
  243.                     }
  244.                     src->moltiplier = src->moltiplier + 1;
  245.                 }
  246.                 src->startRead = current_section;
  247.             }
  248.         }
  249.     }
  250. }
  251.  
  252. void streamWAV(void* arg){
  253.     while(1) {
  254.         svcWaitSynchronization(updateStream, U64_MAX);
  255.         svcClearEvent(updateStream);
  256.         wav* src = (wav*)arg;
  257.         u32 bytesRead;
  258.         u32 control;
  259.         while(1){
  260.             if(closeStream){
  261.                 closeStream = false;
  262.                 svcExitThread();
  263.             }
  264.             if (src->encoding == CSND_ENCODING_IMA_ADPCM) control = (src->samplerate / 2) * ((osGetTime() - src->tick) / 1000);
  265.             else control = src->samplerate * src->bytepersample * ((osGetTime() - src->tick) / 1000);
  266.             if (((control) >= (src->size - src->startRead)) && (src->isPlaying)){
  267.                 if (src->streamLoop){
  268.                     src->tick = osGetTime();
  269.                     src->moltiplier = 1;
  270.                 }else{
  271.                     src->isPlaying = false;
  272.                     src->tick = (osGetTime()-src->tick);
  273.                     src->moltiplier = 1;
  274.                     CSND_setchannel_playbackstate(src->ch, 0);
  275.                     if (src->audiobuf2 != NULL) CSND_setchannel_playbackstate(src->ch2, 0);
  276.                         CSND_sharedmemtype0_cmdupdatestate(0);
  277.                 }
  278.                 if (src->audiobuf2 == NULL){
  279.                     FSFILE_Read(src->sourceFile, &bytesRead, src->startRead, src->audiobuf, src->mem_size);
  280.                     u64 i = 0;
  281.                     if (src->big_endian){
  282.                         while (i < (src->mem_size)){
  283.                             u8 tmp = src->audiobuf[i];
  284.                             src->audiobuf[i] = src->audiobuf[i+1];
  285.                             src->audiobuf[i+1] = tmp;
  286.                             i=i+2;
  287.                         }
  288.                     }
  289.                 }else{
  290.                     u8* tmp_buffer = (u8*)linearAlloc(src->mem_size);
  291.                     FSFILE_Read(src->sourceFile, &bytesRead, src->startRead, tmp_buffer, src->mem_size);
  292.                     u32 size_tbp = src->mem_size;
  293.                     u32 off=0;
  294.                     u32 i=0;
  295.                     u16 z;
  296.                     if (src->big_endian){
  297.                         while (i < size_tbp){
  298.                             z=0;
  299.                             while (z < (src->bytepersample/2)){
  300.                                 src->audiobuf[off+z] = tmp_buffer[i+(src->bytepersample/2)-z-1];
  301.                                 src->audiobuf2[off+z] = tmp_buffer[i+(src->bytepersample)-z-1];
  302.                                 z++;
  303.                             }
  304.                             i=i+src->bytepersample;
  305.                             off=off+(src->bytepersample/2);
  306.                         }
  307.                     }else{
  308.                         while (i < size_tbp){
  309.                             z=0;
  310.                             while (z < (src->bytepersample/2)){
  311.                                 src->audiobuf[off+z] = tmp_buffer[i+z];
  312.                                 src->audiobuf2[off+z] = tmp_buffer[i+z+(src->bytepersample/2)];
  313.                                 z++;
  314.                             }
  315.                             i=i+src->bytepersample;
  316.                             off=off+(src->bytepersample/2);
  317.                         }
  318.                     }
  319.                     linearFree(tmp_buffer);
  320.                 }
  321.             }else if (((control) > ((src->mem_size / 2) * src->moltiplier)) && (src->isPlaying)){
  322.                 if ((src->moltiplier % 2) == 1){
  323.                     //Update and flush first half-buffer
  324.                     if (src->audiobuf2 == NULL){
  325.                         if (src->encoding == CSND_ENCODING_IMA_ADPCM){ //ADPCM Decoding TODO
  326.                             u32 buffer_headers_num = ((src->mem_size)/2) / src->bytepersample;
  327.                             u8* tmp_audiobuf = (u8*)linearAlloc((src->mem_size)/2);
  328.                             FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(((src->mem_size)/2)*(src->moltiplier + 1)), tmp_audiobuf, (src->mem_size)/2);
  329.                             int z=0,i=0;
  330.                             while (i < (src->mem_size/2)){
  331.                                 src->audiobuf[z] = tmp_audiobuf[i];
  332.                                 z++;
  333.                                 i++;
  334.                                 if ((i % src->bytepersample) == 0) i=i+4;
  335.                             }
  336.                             linearFree(tmp_audiobuf);
  337.                         }else{ //PCM-16 Decoding
  338.                             FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(((src->mem_size)/2)*(src->moltiplier + 1)), src->audiobuf, (src->mem_size)/2);
  339.                             u64 i = 0;
  340.                             if (bytesRead != ((src->mem_size)/2)){
  341.                                 FSFILE_Read(src->sourceFile, &bytesRead, src->startRead, src->audiobuf, (src->mem_size)/2);
  342.                                 src->moltiplier = src->moltiplier + 1;
  343.                             }
  344.                             if (src->big_endian){
  345.                                 while (i < ((src->mem_size)/2)){
  346.                                     u8 tmp = src->audiobuf[i];
  347.                                     src->audiobuf[i] = src->audiobuf[i+1];
  348.                                     src->audiobuf[i+1] = tmp;
  349.                                     i=i+2;
  350.                                 }
  351.                             }
  352.                         }
  353.                         src->moltiplier = src->moltiplier + 1;
  354.                     }else{
  355.                         u8* tmp_buffer = (u8*)linearAlloc((src->mem_size)/2);
  356.                         FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(src->mem_size/2)*(src->moltiplier + 1), tmp_buffer, (src->mem_size)/2);
  357.                         if (bytesRead != ((src->mem_size)/2)){
  358.                             FSFILE_Read(src->sourceFile, &bytesRead, src->startRead, tmp_buffer, (src->mem_size)/2);
  359.                             src->moltiplier = src->moltiplier + 1;
  360.                         }
  361.                         src->moltiplier = src->moltiplier + 1;
  362.                         u32 size_tbp = (src->mem_size)/2;
  363.                         u32 off=0;
  364.                         u32 i=0;
  365.                         u16 z;
  366.                         if (src->big_endian){
  367.                             while (i < size_tbp){
  368.                                 z=0;
  369.                                 while (z < (src->bytepersample/2)){
  370.                                     src->audiobuf[off+z] = tmp_buffer[i+(src->bytepersample/2)-z-1];
  371.                                     src->audiobuf2[off+z] = tmp_buffer[i+(src->bytepersample)-z-1];
  372.                                     z++;
  373.                                 }
  374.                                 i=i+src->bytepersample;
  375.                                 off=off+(src->bytepersample/2);
  376.                             }
  377.                         }else{
  378.                             while (i < size_tbp){
  379.                                 z=0;
  380.                                 while (z < (src->bytepersample/2)){
  381.                                     src->audiobuf[off+z] = tmp_buffer[i+z];
  382.                                     src->audiobuf2[off+z] = tmp_buffer[i+z+(src->bytepersample/2)];
  383.                                     z++;
  384.                                 }
  385.                                 i=i+src->bytepersample;
  386.                                 off=off+(src->bytepersample/2);
  387.                             }
  388.                         }
  389.                         linearFree(tmp_buffer);
  390.                     }
  391.                 }else{
  392.                     u32 bytesRead;
  393.                     //Update and flush second half-buffer
  394.                     if (src->audiobuf2 == NULL){
  395.                         if (src->encoding == CSND_ENCODING_IMA_ADPCM){ // ADPCM Decoding TODO
  396.                             u32 buffer_headers_num = ((src->mem_size)/2) / src->bytepersample;
  397.                             u8* tmp_audiobuf = (u8*)linearAlloc((src->mem_size)/2);
  398.                             FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(((src->mem_size)/2)*(src->moltiplier + 1)), tmp_audiobuf, (src->mem_size)/2);
  399.                             int z=0,i=0;
  400.                             while (i < (src->mem_size/2)){
  401.                                 src->audiobuf[z+(src->mem_size/2)] = tmp_audiobuf[i];
  402.                                 z++;
  403.                                 i++;
  404.                                 if ((i % src->bytepersample) == 0) i=i+4;
  405.                             }
  406.                             linearFree(tmp_audiobuf);
  407.                         }else{ // PCM-16 Decoding
  408.                             FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(((src->mem_size)/2)*(src->moltiplier + 1)), src->audiobuf+((src->mem_size)/2), (src->mem_size)/2);
  409.                             if (src->big_endian){
  410.                                 u64 i = 0;
  411.                                 while (i < ((src->mem_size)/2)){
  412.                                     u8 tmp = src->audiobuf[i+((src->mem_size)/2)];
  413.                                     src->audiobuf[i+((src->mem_size)/2)] = src->audiobuf[i+((src->mem_size)/2)+1];
  414.                                     src->audiobuf[i+((src->mem_size)/2)+1] = tmp;
  415.                                     i=i+2;
  416.                                 }
  417.                             }
  418.                         }
  419.                         src->moltiplier = src->moltiplier + 1;
  420.                     }else{
  421.                         u8* tmp_buffer = (u8*)linearAlloc((src->mem_size)/2);
  422.                         FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(src->mem_size/2)*(src->moltiplier + 1), tmp_buffer, (src->mem_size)/2);
  423.                         src->moltiplier = src->moltiplier + 1;
  424.                         u32 size_tbp = (src->mem_size)/2;
  425.                         u32 off=0;
  426.                         u32 i=0;
  427.                         u16 z;
  428.                         if (src->big_endian){
  429.                             while (i < size_tbp){
  430.                                 z=0;
  431.                                 while (z < (src->bytepersample/2)){
  432.                                     src->audiobuf[(src->mem_size)/4+off+z] = tmp_buffer[i+(src->bytepersample/2)-z-1];
  433.                                     src->audiobuf2[(src->mem_size)/4+off+z] = tmp_buffer[i+(src->bytepersample)-z-1];
  434.                                     z++;
  435.                                 }
  436.                                 z=0;
  437.                                 i=i+src->bytepersample;
  438.                                 off=off+(src->bytepersample/2);
  439.                             }
  440.                         }else{
  441.                             while (i < size_tbp){
  442.                                 z=0;
  443.                                 while (z < (src->bytepersample/2)){
  444.                                     src->audiobuf[(src->mem_size)/4+off+z] = tmp_buffer[i+z];
  445.                                     src->audiobuf2[(src->mem_size)/4+off+z] = tmp_buffer[i+z+(src->bytepersample/2)];
  446.                                     z++;
  447.                                 }
  448.                                 i=i+src->bytepersample;
  449.                                 off=off+(src->bytepersample/2);
  450.                             }
  451.                         }
  452.                         linearFree(tmp_buffer);
  453.                     }
  454.                 }
  455.             }
  456.         }
  457.     }
  458.  
  459.     /*//if (src->encoding == CSND_ENCODING_VORBIS) return lua_streamOgg(L);
  460.     */
  461.        
  462. }
  463.  
  464. static int lua_openogg(lua_State *L)
  465. {  
  466.     int argc = lua_gettop(L);
  467.     if ((argc != 1) && (argc != 2)) return luaL_error(L, "wrong number of arguments");
  468.     const char *file_tbo = luaL_checkstring(L, 1); //Filename
  469.    
  470.     // Streaming support
  471.     bool mem_size = false;
  472.     if (argc == 2) mem_size = lua_toboolean(L, 2);
  473.    
  474.     char pcmout[4096]; //Does it can be incresed or it crashes if increased?
  475.    
  476.     // Using stdio instead of FS
  477.     char myFile[512];
  478.     strcpy(myFile,"sdmc:");
  479.     strcat(myFile,file_tbo);
  480.     sdmcInit();
  481.    
  482.     // Initializing libogg and vorbisfile
  483.     int eof=0;
  484.     OggVorbis_File* vf = (OggVorbis_File*)malloc(sizeof(OggVorbis_File));
  485.     static int current_section;
  486.    
  487.     // Opening a valid OGG music file
  488.     FILE* fp = fopen(myFile,"rb");
  489.     if(ov_open(fp, vf, NULL, 0) != 0)
  490.     {
  491.         fclose(fp);
  492.         return luaL_error(L, "corrupt OGG file.");
  493.     }
  494.    
  495.     // Allocating music info
  496.     wav *wav_file = (wav*)malloc(sizeof(wav));
  497.     wav_file->magic = 0x4C534E44;
  498.     vorbis_info* my_info = ov_info(vf,-1);
  499.     wav_file->samplerate = my_info->rate;
  500.     wav_file->big_endian = false;
  501.     wav_file->encoding = CSND_ENCODING_VORBIS;
  502.     wav_file->size = ov_time_total(vf,-1) * 2 * my_info->rate;
  503.     wav_file->startRead = 0;
  504.     strcpy(wav_file->author,"");
  505.     strcpy(wav_file->title,"");
  506.     wav_file->isPlaying = false;
  507.     wav_file->bytepersample = 2;
  508.    
  509.     // Decoding OGG buffer
  510.     int i=0;
  511.     if (my_info->channels == 1){ //Mono buffer
  512.         if (mem_size){
  513.             wav_file->moltiplier = 1;
  514.             wav_file->mem_size = wav_file->size / 2;
  515.             while (wav_file->mem_size > STREAM_MAX_ALLOC){
  516.                 wav_file->mem_size = wav_file->mem_size / 2;
  517.             }
  518.             wav_file->audiobuf = (u8*)linearAlloc(wav_file->mem_size);
  519.         }else{
  520.             wav_file->audiobuf = (u8*)linearAlloc(wav_file->size);
  521.             wav_file->mem_size = mem_size;
  522.         }
  523.         wav_file->audiobuf2 = NULL;
  524.         while(!eof){
  525.             long ret=ov_read(vf,pcmout,sizeof(pcmout),0,2,1,&current_section);
  526.             if (ret == 0) {
  527.            
  528.                 // EOF
  529.                 eof=1;
  530.                
  531.             } else if (ret < 0) {
  532.            
  533.                 // Error handling
  534.                 if(ret==OV_EBADLINK){
  535.                     return luaL_error(L, "corrupt bitstream section.");
  536.                 }
  537.                
  538.             } else {
  539.            
  540.                 // Copying decoded block to PCM16 audiobuffer
  541.                 memcpy(&wav_file->audiobuf[i],pcmout,ret);
  542.                 i = i + ret;
  543.                 if ((mem_size) && (i >= wav_file->mem_size)) break;
  544.             }
  545.         }
  546.     }else{ //Stereo buffer
  547.         u8* tmp_buf;
  548.         u32 size_tbp;
  549.         if (mem_size){
  550.             wav_file->moltiplier = 1;
  551.             wav_file->bytepersample = 2;
  552.             wav_file->mem_size = wav_file->size / 2;
  553.             u8 molt = 4;
  554.             if (ov_time_total(vf,-1) < 70) molt = 2; // Temporary patch for little files
  555.             while (wav_file->mem_size > STREAM_MAX_ALLOC * molt){
  556.                 wav_file->mem_size = wav_file->mem_size / 2;
  557.             }
  558.             size_tbp = wav_file->mem_size;
  559.             tmp_buf = (u8*)linearAlloc(wav_file->mem_size);
  560.             wav_file->audiobuf = (u8*)linearAlloc(wav_file->mem_size / 2);
  561.             wav_file->audiobuf2 = (u8*)linearAlloc(wav_file->mem_size / 2);
  562.         }else{
  563.             wav_file->bytepersample = 4;
  564.             size_tbp = wav_file->size * 2;
  565.             tmp_buf = (u8*)linearAlloc(wav_file->size * 2);
  566.             wav_file->audiobuf = (u8*)linearAlloc(wav_file->size);
  567.             wav_file->audiobuf2 = (u8*)linearAlloc(wav_file->size);
  568.             wav_file->mem_size = mem_size;
  569.         }
  570.        
  571.         while(!eof){
  572.             long ret=ov_read(vf,pcmout,sizeof(pcmout),0,2,1,&current_section);
  573.             if (ret == 0) {
  574.            
  575.                 // EOF
  576.                 eof=1;
  577.                
  578.             } else if (ret < 0) {
  579.            
  580.                 // Error handling
  581.                 if(ret==OV_EBADLINK){
  582.                     return luaL_error(L, "corrupt bitstream section.");
  583.                 }
  584.                
  585.             } else {
  586.            
  587.                 // Copying decoded block to PCM16 audiobuffer
  588.                 memcpy(&tmp_buf[i],pcmout,ret);
  589.                 i = i + ret;
  590.                 if ((mem_size) && (i >= wav_file->mem_size)) break;
  591.             }
  592.         }
  593.        
  594.         // Separating left and right channels
  595.         int z;
  596.         int j=0;
  597.         for (z=0; z < size_tbp; z=z+4){
  598.             wav_file->audiobuf[j] = tmp_buf[z];
  599.             wav_file->audiobuf[j+1] = tmp_buf[z+1];
  600.             wav_file->audiobuf2[j] = tmp_buf[z+2];
  601.             wav_file->audiobuf2[j+1] = tmp_buf[z+3];
  602.             j=j+2;
  603.         }
  604.         linearFree(tmp_buf);
  605.        
  606.     }
  607.    
  608.     if (!mem_size){
  609.    
  610.         // Deallocate OGG decoder resources and close file if not streaming
  611.         ov_clear(vf);
  612.         sdmcExit();
  613.        
  614.     }else{
  615.         wav_file->startRead = current_section;
  616.         wav_file->sourceFile = (u32)vf;
  617.     }
  618.    
  619.     // Push wav struct offset to LUA stack
  620.     lua_pushinteger(L,(u32)wav_file);
  621.    
  622.     return 1;
  623. }
  624.  
  625. static int lua_openwav(lua_State *L)
  626. {
  627.     int argc = lua_gettop(L);
  628.     if ((argc != 1) && (argc != 2)) return luaL_error(L, "wrong number of arguments");
  629.     const char *file_tbo = luaL_checkstring(L, 1);
  630.     bool mem_size = false;
  631.     if (argc == 2) mem_size = lua_toboolean(L, 2);
  632.     Handle fileHandle;
  633.     FS_archive sdmcArchive=(FS_archive){ARCH_SDMC, (FS_path){PATH_EMPTY, 1, (u8*)""}};
  634.     FS_path filePath=FS_makePath(PATH_CHAR, file_tbo);
  635.     Result ret=FSUSER_OpenFileDirectly(NULL, &fileHandle, sdmcArchive, filePath, FS_OPEN_READ, FS_ATTRIBUTE_NONE);
  636.     if(ret) return luaL_error(L, "error opening file");
  637.     u32 magic,samplerate,bytesRead,jump,chunk=0x00000000;
  638.     u16 audiotype;
  639.     FSFILE_Read(fileHandle, &bytesRead, 0, &magic, 4);
  640.     if (magic == 0x46464952){
  641.         wav *wav_file = (wav*)malloc(sizeof(wav));
  642.         strcpy(wav_file->author,"");
  643.         strcpy(wav_file->title,"");
  644.         u64 size;
  645.         wav_file->big_endian = false;
  646.         u32 pos = 16;  
  647.         while (chunk != 0x61746164){
  648.             FSFILE_Read(fileHandle, &bytesRead, pos, &jump, 4);
  649.             pos=pos+4+jump;
  650.             FSFILE_Read(fileHandle, &bytesRead, pos, &chunk, 4);   
  651.             pos=pos+4;
  652.    
  653.             //Chunk LIST detection
  654.             if (chunk == 0x5453494C){
  655.                 u32 chunk_size;
  656.                 u32 subchunk;
  657.                 u32 subchunk_size;
  658.                 u32 sub_pos = pos+4;
  659.                 FSFILE_Read(fileHandle, &bytesRead, sub_pos, &subchunk, 4);
  660.                 if (subchunk == 0x4F464E49){
  661.                     sub_pos = sub_pos+4;
  662.                     FSFILE_Read(fileHandle, &bytesRead, pos, &chunk_size, 4);
  663.                     while (sub_pos < (chunk_size + pos + 4)){
  664.                         FSFILE_Read(fileHandle, &bytesRead, sub_pos, &subchunk, 4);
  665.                         FSFILE_Read(fileHandle, &bytesRead, sub_pos+4, &subchunk_size, 4);
  666.                         if (subchunk == 0x54524149){
  667.                             char* author = (char*)malloc(subchunk_size * sizeof(char));
  668.                             FSFILE_Read(fileHandle, &bytesRead, sub_pos+8, author, subchunk_size);
  669.                             strcpy(wav_file->author,author);
  670.                             wav_file->author[subchunk_size+1] = 0;
  671.                             free(author);
  672.                         }else if (subchunk == 0x4D414E49){
  673.                             char* title = (char*)malloc(subchunk_size * sizeof(char));
  674.                             FSFILE_Read(fileHandle, &bytesRead, sub_pos+8, title, subchunk_size);
  675.                             strcpy(wav_file->title,title);
  676.                             wav_file->title[subchunk_size+1] = 0;
  677.                             free(title);
  678.                         }
  679.                         sub_pos = sub_pos + 8 + subchunk_size;
  680.                         u8 checksum;
  681.                         FSFILE_Read(fileHandle, &bytesRead, sub_pos, &checksum, 1); //Prevent errors switching subchunks
  682.                         if (checksum == 0) sub_pos++;
  683.                     }
  684.                 }
  685.             }
  686.    
  687.         }
  688.         FSFILE_GetSize(fileHandle, &size);
  689.         FSFILE_Read(fileHandle, &bytesRead, 22, &audiotype, 2);
  690.         FSFILE_Read(fileHandle, &bytesRead, 24, &samplerate, 4);
  691.         u16 raw_enc;
  692.         FSFILE_Read(fileHandle, &bytesRead, 20, &raw_enc, 2);
  693.         FSFILE_Read(fileHandle, &bytesRead, 32, &(wav_file->bytepersample), 2);
  694.         if (raw_enc == 0x01) wav_file->encoding = CSND_ENCODING_PCM16;
  695.         else if (raw_enc == 0x11) wav_file->encoding = CSND_ENCODING_IMA_ADPCM;
  696.         wav_file->mem_size = mem_size;
  697.         wav_file->samplerate = samplerate;
  698.         if (audiotype == 1){
  699.             if (mem_size){
  700.                 wav_file->moltiplier = 1;
  701.                 wav_file->isPlaying = false;
  702.                 wav_file->mem_size = (size-(pos+4));
  703.                 while (wav_file->mem_size > STREAM_MAX_ALLOC){
  704.                     wav_file->mem_size = wav_file->mem_size / 2;
  705.                 }
  706.                 wav_file->sourceFile = fileHandle;
  707.                 wav_file->startRead = (pos+4);
  708.                 if (raw_enc == 0x11){ // ADPCM Decoding
  709.                     u32 buffer_headers_num = (wav_file->mem_size) / wav_file->bytepersample;
  710.                     u8* tmp_audiobuf = (u8*)linearAlloc(wav_file->mem_size);
  711.                     FSFILE_Read(fileHandle, &bytesRead, pos+4, tmp_audiobuf, wav_file->mem_size);
  712.                     wav_file->audiobuf = (u8*)linearAlloc(wav_file->mem_size-buffer_headers_num*4);
  713.                     int z=0,i=0;
  714.                     while (i < wav_file->mem_size){
  715.                         wav_file->audiobuf[z] = tmp_audiobuf[i];
  716.                         z++;
  717.                         i++;
  718.                         if ((i % wav_file->bytepersample) == 0) i=i+4;
  719.                     }
  720.                     linearFree(tmp_audiobuf);
  721.                 }else{ // PCM-16 Decoding
  722.                     wav_file->audiobuf = (u8*)linearAlloc(wav_file->mem_size);
  723.                     FSFILE_Read(fileHandle, &bytesRead, wav_file->startRead, wav_file->audiobuf, wav_file->mem_size);
  724.                 }
  725.                 wav_file->audiobuf2 = NULL;
  726.                 wav_file->size = size;
  727.             }else{
  728.                 if (raw_enc == 0x11){ // ADPCM Decoding
  729.                     u32 headers_num = (size-(pos+4)) / wav_file->bytepersample;
  730.                     u8* tmp_audiobuf = (u8*)linearAlloc(size-(pos+4));
  731.                     FSFILE_Read(fileHandle, &bytesRead, pos+4, tmp_audiobuf, size-(pos+4));
  732.                     wav_file->audiobuf = (u8*)linearAlloc(size-(pos+4)-headers_num*4);
  733.                     int z=0,i=0;
  734.                     while (i < size){
  735.                         wav_file->audiobuf[z] = tmp_audiobuf[i];
  736.                         z++;
  737.                         i++;
  738.                         if ((i % wav_file->bytepersample) == 0) i=i+4;
  739.                     }
  740.                     linearFree(tmp_audiobuf);
  741.                     size = size-(pos+4) - headers_num * 4;
  742.                 }else{ // PCM-16 Decoding
  743.                     wav_file->audiobuf = (u8*)linearAlloc(size-(pos+4));
  744.                     FSFILE_Read(fileHandle, &bytesRead, pos+4, wav_file->audiobuf, size-(pos+4));
  745.                     size = size-(pos+4);
  746.                 }
  747.                 wav_file->audiobuf2 = NULL;
  748.                 wav_file->size = size;
  749.                 wav_file->startRead = 0;
  750.             }
  751.         }else{
  752.             // I must reordinate my buffer in order to play stereo sound (Thanks CSND/FS libraries .-.)
  753.             u32 size_tbp;
  754.             u8* tmp_buffer;
  755.             if (mem_size){
  756.                 wav_file->moltiplier = 1;
  757.                 wav_file->sourceFile = fileHandle;
  758.                 wav_file->isPlaying = false;
  759.                 wav_file->startRead = (pos+4);
  760.                 wav_file->size = size;
  761.                 wav_file->mem_size = (size-(pos+4));
  762.                 while (wav_file->mem_size > STREAM_MAX_ALLOC * 10){
  763.                     wav_file->mem_size = wav_file->mem_size / 2;
  764.                 }
  765.                 tmp_buffer = (u8*)linearAlloc(wav_file->mem_size);
  766.                 wav_file->audiobuf = (u8*)linearAlloc(wav_file->mem_size/2);
  767.                 wav_file->audiobuf2 = (u8*)linearAlloc(wav_file->mem_size/2);
  768.                 FSFILE_Read(fileHandle, &bytesRead, wav_file->startRead, tmp_buffer, wav_file->mem_size);
  769.                 size_tbp = wav_file->mem_size;
  770.             }else{
  771.                 tmp_buffer = (u8*)linearAlloc((size-(pos+4)));
  772.                 size_tbp = size-(pos+4);
  773.                 wav_file->startRead = 0;
  774.                 wav_file->size = (size_tbp)/2;
  775.                 FSFILE_Read(fileHandle, &bytesRead, pos+4, tmp_buffer, size-(pos+4));
  776.             }
  777.             u32 off=0;
  778.             u32 i=0;
  779.             u16 z;
  780.             if (raw_enc == 0x01){ //PCM16 Decoding
  781.                 wav_file->audiobuf = (u8*)linearAlloc((size-(pos+4))/2);
  782.                 wav_file->audiobuf2 = (u8*)linearAlloc((size-(pos+4))/2);
  783.                 while (i < size_tbp){
  784.                     z=0;
  785.                     while (z < (wav_file->bytepersample/2)){
  786.                         wav_file->audiobuf[off+z] = tmp_buffer[i+z];
  787.                         wav_file->audiobuf2[off+z] = tmp_buffer[i+z+(wav_file->bytepersample/2)];
  788.                         z++;
  789.                     }
  790.                     i=i+wav_file->bytepersample;
  791.                     off=off+(wav_file->bytepersample/2);
  792.                 }
  793.             }else if (raw_enc == 0x11){ //ADPCM Decoding
  794.                 u32 headers_num = (size_tbp) / wav_file->bytepersample;
  795.                 wav_file->audiobuf = (u8*)linearAlloc((size_tbp-headers_num*8)/2);
  796.                 wav_file->audiobuf2 = (u8*)linearAlloc((size_tbp-headers_num*8)/2);
  797.                 int z=0,i=0;
  798.                 while (i < size_tbp){
  799.                     wav_file->audiobuf[z] = tmp_buffer[i++];
  800.                     wav_file->audiobuf2[z++] = tmp_buffer[i+3];
  801.                     wav_file->audiobuf[z] = tmp_buffer[i++];
  802.                     wav_file->audiobuf2[z++] = tmp_buffer[i+3];
  803.                     wav_file->audiobuf[z] = tmp_buffer[i++];
  804.                     wav_file->audiobuf2[z++] = tmp_buffer[i+3];
  805.                     wav_file->audiobuf[z] = tmp_buffer[i++];
  806.                     wav_file->audiobuf2[z++] = tmp_buffer[i+3];
  807.                     i=i+4;
  808.                     if ((i % wav_file->bytepersample) == 0) i=i+8;
  809.                 }
  810.             }
  811.             linearFree(tmp_buffer);
  812.         }
  813.         wav_file->magic = 0x4C534E44;
  814.         lua_pushinteger(L,(u32)wav_file);
  815.     }
  816.     if (!mem_size){
  817.         FSFILE_Close(fileHandle);
  818.         svcCloseHandle(fileHandle);
  819.     }
  820.     return 1;
  821. }
  822.  
  823. static u32 Endian_UInt32_Conversion(u32 value){
  824.    return ((value >> 24) & 0x000000FF) | ((value >> 8) & 0x0000FF00) | ((value << 8) & 0x00FF0000) | ((value << 24) & 0xFF000000);
  825. }
  826.  
  827. static u16 Endian_UInt16_Conversion(u16 value){
  828.    return (u16)(((value >> 8) & 0x00FF) | ((value << 8) & 0xFF00));
  829. }
  830. static int lua_openaiff(lua_State *L)
  831. {
  832.     int argc = lua_gettop(L);
  833.     if ((argc != 1) && (argc != 2)) return luaL_error(L, "wrong number of arguments");
  834.     const char *file_tbo = luaL_checkstring(L, 1);
  835.     bool mem_size = false;
  836.     if (argc == 2) mem_size = lua_toboolean(L, 2);
  837.     Handle fileHandle;
  838.     FS_archive sdmcArchive=(FS_archive){ARCH_SDMC, (FS_path){PATH_EMPTY, 1, (u8*)""}};
  839.     FS_path filePath=FS_makePath(PATH_CHAR, file_tbo);
  840.     Result ret=FSUSER_OpenFileDirectly(NULL, &fileHandle, sdmcArchive, filePath, FS_OPEN_READ, FS_ATTRIBUTE_NONE);
  841.     if(ret) return luaL_error(L, "error opening file");
  842.     u32 magic,bytesRead,jump,chunk=0x00000000;
  843.     u16 samplerate;
  844.     u16 audiotype;
  845.     FSFILE_Read(fileHandle, &bytesRead, 8, &magic, 4);
  846.     if (magic == 0x46464941){
  847.     wav *wav_file = (wav*)malloc(sizeof(wav));
  848.     strcpy(wav_file->author,"");
  849.     strcpy(wav_file->title,"");
  850.     wav_file->encoding = CSND_ENCODING_PCM16;
  851.     u64 size;
  852.     wav_file->big_endian = true;
  853.     u32 pos = 12;  
  854.     FSFILE_Read(fileHandle, &bytesRead, pos, &chunk, 4);
  855.     while (chunk != 0x444E5353){
  856.    
  857.     //Chunks detection
  858.     if (chunk == 0x454D414E){ //NAME Chunk
  859.         u32 chunk_size;
  860.         FSFILE_Read(fileHandle, &bytesRead, pos+4, &chunk_size, 4);
  861.         chunk_size = Endian_UInt32_Conversion(chunk_size);
  862.         char* title = (char*)malloc(chunk_size * sizeof(char));
  863.         FSFILE_Read(fileHandle, &bytesRead, pos+8, title, chunk_size);
  864.         strcpy(wav_file->title,title);
  865.         wav_file->title[chunk_size+1] = 0;
  866.         free(title);
  867.     }else if (chunk == 0x4D4D4F43){ //COMM Chunk
  868.         FSFILE_Read(fileHandle, &bytesRead, pos+8, &audiotype, 2);
  869.         audiotype = audiotype / 256;
  870.         FSFILE_Read(fileHandle, &bytesRead, pos+14, &(wav_file->bytepersample), 2);
  871.         wav_file->bytepersample = (wav_file->bytepersample / 2048) * audiotype;
  872.         FSFILE_Read(fileHandle, &bytesRead, pos+18, &samplerate, 2);
  873.         samplerate = Endian_UInt16_Conversion(samplerate);
  874.     }
  875.    
  876.     pos=pos+4;
  877.     FSFILE_Read(fileHandle, &bytesRead, pos, &jump, 4);
  878.     pos=pos+4+Endian_UInt32_Conversion(jump);
  879.     FSFILE_Read(fileHandle, &bytesRead, pos, &chunk, 4);   
  880.     }
  881.     pos=pos+4;
  882.     FSFILE_GetSize(fileHandle, &size);
  883.     wav_file->mem_size = mem_size;
  884.     wav_file->samplerate = samplerate;
  885.     if (audiotype == 1){
  886.     if (mem_size){
  887.     wav_file->moltiplier = 1;
  888.     wav_file->isPlaying = false;
  889.     wav_file->mem_size = (size-(pos+4));
  890.     while (wav_file->mem_size > STREAM_MAX_ALLOC * 2){
  891.         wav_file->mem_size = wav_file->mem_size / 2;
  892.     }
  893.     wav_file->sourceFile = fileHandle;
  894.     wav_file->audiobuf = (u8*)linearAlloc(wav_file->mem_size);
  895.     wav_file->startRead = (pos+4);
  896.     FSFILE_Read(fileHandle, &bytesRead, wav_file->startRead, wav_file->audiobuf, wav_file->mem_size);
  897.    
  898.     // Changing endianess
  899.     u64 i = 0;
  900.     while (i < wav_file->mem_size){
  901.         u8 tmp = wav_file->audiobuf[i];
  902.         wav_file->audiobuf[i] = wav_file->audiobuf[i+1];
  903.         wav_file->audiobuf[i+1] = tmp;
  904.         i=i+2;
  905.     }
  906.    
  907.     wav_file->audiobuf2 = NULL;
  908.     wav_file->size = size;
  909.     }else{
  910.     wav_file->audiobuf = (u8*)linearAlloc(size-(pos+4));
  911.     FSFILE_Read(fileHandle, &bytesRead, pos+4, wav_file->audiobuf, size-(pos+4));
  912.    
  913.     // Changing endianess
  914.     u64 i = 0;
  915.     while (i < (size-(pos+4))){
  916.         u8 tmp = wav_file->audiobuf[i];
  917.         wav_file->audiobuf[i] = wav_file->audiobuf[i+1];
  918.         wav_file->audiobuf[i+1] = tmp;
  919.         i=i+2;
  920.     }
  921.    
  922.     wav_file->audiobuf2 = NULL;
  923.     wav_file->size = size-(pos+4);
  924.     wav_file->startRead = 0;
  925.     wav_file->isPlaying = false;
  926.     }
  927.     }else{
  928.     // I must reordinate my buffer in order to play stereo sound and change endianess
  929.     u32 size_tbp;
  930.     u8* tmp_buffer;
  931.     if (mem_size){
  932.     wav_file->moltiplier = 1;
  933.     wav_file->sourceFile = fileHandle;
  934.     wav_file->isPlaying = false;
  935.     wav_file->startRead = (pos+4);
  936.     wav_file->size = size;
  937.     wav_file->mem_size = (size-(pos+4));
  938.     while (wav_file->mem_size > STREAM_MAX_ALLOC * 10){
  939.         wav_file->mem_size = wav_file->mem_size / 2;
  940.     }
  941.     tmp_buffer = (u8*)linearAlloc(wav_file->mem_size);
  942.     wav_file->audiobuf = (u8*)linearAlloc(wav_file->mem_size/2);
  943.     wav_file->audiobuf2 = (u8*)linearAlloc(wav_file->mem_size/2);
  944.     FSFILE_Read(fileHandle, &bytesRead, wav_file->startRead, tmp_buffer, wav_file->mem_size);
  945.     size_tbp = wav_file->mem_size;
  946.     }else{
  947.     tmp_buffer = (u8*)linearAlloc((size-(pos+4)));
  948.     wav_file->audiobuf = (u8*)linearAlloc((size-(pos+4))/2);
  949.     wav_file->audiobuf2 = (u8*)linearAlloc((size-(pos+4))/2);
  950.     wav_file->startRead = 0;
  951.     size_tbp = size-(pos+4);
  952.     wav_file->size = (size_tbp)/2;
  953.     FSFILE_Read(fileHandle, &bytesRead, pos+4, tmp_buffer, size-(pos+4));
  954.     }
  955.     u32 off=0;
  956.     u32 i=0;
  957.     u16 z;
  958.     while (i < size_tbp){
  959.     z=0;
  960.     while (z < (wav_file->bytepersample/2)){
  961.     wav_file->audiobuf[off+z] = tmp_buffer[i+(wav_file->bytepersample/2)-z-1];
  962.     wav_file->audiobuf2[off+z] = tmp_buffer[i+(wav_file->bytepersample)-z-1];
  963.     z++;
  964.     }
  965.     i=i+wav_file->bytepersample;
  966.     off=off+(wav_file->bytepersample/2);
  967.     }
  968.     linearFree(tmp_buffer);
  969.     }
  970.     wav_file->magic = 0x4C534E44;
  971.     lua_pushinteger(L,(u32)wav_file);
  972.     }
  973.     if (!mem_size){
  974.     FSFILE_Close(fileHandle);
  975.     svcCloseHandle(fileHandle);
  976.     }
  977.     return 1;
  978. }
  979.  
  980. static int lua_soundinit(lua_State *L)
  981. {
  982.     int argc = lua_gettop(L);
  983.     if (argc != 0) return luaL_error(L, "wrong number of arguments");
  984.     if (!isCSND){
  985.         CSND_initialize(NULL);
  986.         isCSND = true;
  987.     }
  988.     return 0;
  989. }
  990.  
  991. static int lua_playWav(lua_State *L)
  992. {
  993.     int argc = lua_gettop(L);
  994.     if ((argc != 3) && (argc != 4)) return luaL_error(L, "wrong number of arguments");
  995.     wav* src = (wav*)luaL_checkinteger(L, 1);
  996.     #ifndef SKIP_ERROR_HANDLING
  997.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  998.     #endif
  999.     closeStream = false;
  1000.     int loop = luaL_checkinteger(L, 2);
  1001.     u32 ch = luaL_checkinteger(L, 3);
  1002.     u32 ch2;
  1003.     bool non_native_encode = false;
  1004.     ThreadFunc streamFunction = streamWAV;
  1005.     u8 tmp_encode;
  1006.     if (argc == 4) ch2 = luaL_checkinteger(L, 4);
  1007.     if (src->encoding == CSND_ENCODING_VORBIS){
  1008.         streamFunction = streamOGG;
  1009.         tmp_encode = src->encoding;
  1010.         src->encoding = CSND_ENCODING_PCM16;
  1011.         non_native_encode = true;
  1012.     }
  1013.     if (src->audiobuf2 == NULL){
  1014.         if (src->mem_size > 0){
  1015.         if (loop == 0) src->streamLoop = false;
  1016.         else src->streamLoop = true;
  1017.         svcCreateEvent(&updateStream,0);
  1018.         u32 *threadStack = (u32*)memalign(32, 32768);
  1019.         src->thread = threadStack;
  1020.         svcSignalEvent(updateStream);
  1021.         Result ret = svcCreateThread(&streamThread, streamFunction, (u32)src, &threadStack[8192], 0x18, 1);
  1022.         My_CSND_playsound(ch, CSND_LOOP_ENABLE, src->encoding, src->samplerate, (u32*)src->audiobuf, (u32*)(src->audiobuf), src->mem_size, 0xFFFF, 0xFFFF);
  1023.         }else{
  1024.         My_CSND_playsound(ch, loop, src->encoding, src->samplerate, (u32*)src->audiobuf, (u32*)(src->audiobuf), src->size, 0xFFFF, 0xFFFF);
  1025.         }
  1026.         src->ch = ch;
  1027.         src->tick = osGetTime();
  1028.         CSND_setchannel_playbackstate(ch, 1);
  1029.         CSND_sharedmemtype0_cmdupdatestate(0);
  1030.     }else{
  1031.         if (src->mem_size > 0){
  1032.         if (loop == 0) src->streamLoop = false;
  1033.         else src->streamLoop = true;
  1034.         svcCreateEvent(&updateStream,0);
  1035.         u32 *threadStack = (u32*)memalign(32, 8192);
  1036.         src->thread = threadStack;
  1037.         svcSignalEvent(updateStream);
  1038.         Result ret = svcCreateThread(&streamThread, streamFunction, (u32)src, &threadStack[2048], 0x18, 1);
  1039.         My_CSND_playsound(ch, CSND_LOOP_ENABLE, src->encoding, src->samplerate, (u32*)src->audiobuf, (u32*)(src->audiobuf), (src->mem_size)/2, 0xFFFF, 0);
  1040.         My_CSND_playsound(ch2, CSND_LOOP_ENABLE, src->encoding, src->samplerate, (u32*)src->audiobuf2, (u32*)(src->audiobuf2), (src->mem_size)/2, 0, 0xFFFF);
  1041.         }else{
  1042.         My_CSND_playsound(ch, loop, src->encoding, src->samplerate, (u32*)src->audiobuf, (u32*)(src->audiobuf), src->size, 0xFFFF, 0);
  1043.         My_CSND_playsound(ch2, loop, src->encoding, src->samplerate, (u32*)src->audiobuf2, (u32*)(src->audiobuf2), src->size, 0, 0xFFFF);
  1044.         }
  1045.         src->ch = ch;
  1046.         src->ch2 = ch2;
  1047.         src->tick = osGetTime();
  1048.         CSND_setchannel_playbackstate(ch, 1);
  1049.         CSND_setchannel_playbackstate(ch2, 1);
  1050.         CSND_sharedmemtype0_cmdupdatestate(0);
  1051.     }
  1052.     if (non_native_encode){
  1053.         src->encoding = tmp_encode;
  1054.     }
  1055.     src->isPlaying = true;
  1056.     return 0;
  1057. }
  1058.  
  1059. static int lua_closeWav(lua_State *L)
  1060. {
  1061.     int argc = lua_gettop(L);
  1062.     if (argc != 1) return luaL_error(L, "wrong number of arguments");
  1063.     wav* src = (wav*)luaL_checkinteger(L, 1);
  1064.     #ifndef SKIP_ERROR_HANDLING
  1065.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  1066.     #endif
  1067.     if (src->mem_size > 0){
  1068.         closeStream = true;
  1069.         while (closeStream){} // Wait for thread exiting...
  1070.         svcCloseHandle(updateStream);
  1071.         svcCloseHandle(streamThread);
  1072.         free(src->thread);
  1073.         if (src->encoding == CSND_ENCODING_VORBIS){
  1074.             ov_clear((OggVorbis_File*)src->sourceFile);
  1075.             sdmcExit();
  1076.         }else{
  1077.             FSFILE_Close(src->sourceFile);
  1078.             svcCloseHandle(src->sourceFile);
  1079.         }
  1080.     }
  1081.     linearFree(src->audiobuf);
  1082.     if (src->audiobuf2 != NULL) linearFree(src->audiobuf2);
  1083.     free(src);
  1084.     return 0;
  1085. }
  1086.  
  1087. static int lua_pause(lua_State *L)
  1088. {
  1089.     int argc = lua_gettop(L);
  1090.     if (argc != 1) return luaL_error(L, "wrong number of arguments");
  1091.     wav* src = (wav*)luaL_checkinteger(L, 1);
  1092.     #ifndef SKIP_ERROR_HANDLING
  1093.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  1094.     #endif
  1095.     CSND_setchannel_playbackstate(src->ch, 0);
  1096.     if (src->audiobuf2 != NULL) CSND_setchannel_playbackstate(src->ch2, 0);
  1097.     CSND_sharedmemtype0_cmdupdatestate(0);
  1098.     src->isPlaying = false;
  1099.     src->tick = (osGetTime()-src->tick);
  1100.     return 0;
  1101. }
  1102.  
  1103. static int lua_resume(lua_State *L)
  1104. {
  1105.     int argc = lua_gettop(L);
  1106.     if (argc != 1) return luaL_error(L, "wrong number of arguments");
  1107.     wav* src = (wav*)luaL_checkinteger(L, 1);
  1108.     #ifndef SKIP_ERROR_HANDLING
  1109.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  1110.     #endif
  1111.     CSND_setchannel_playbackstate(src->ch, 1);
  1112.     if (src->audiobuf2 != NULL) CSND_setchannel_playbackstate(src->ch2, 1);
  1113.     CSND_sharedmemtype0_cmdupdatestate(0);
  1114.     src->isPlaying = true;
  1115.     src->tick = (osGetTime()-src->tick);
  1116.     return 0;
  1117. }
  1118.  
  1119. static int lua_wisPlaying(lua_State *L){
  1120. int argc = lua_gettop(L);
  1121.     if (argc != 1) return luaL_error(L, "wrong number of arguments");
  1122.     wav* src = (wav*)luaL_checkinteger(L, 1);
  1123.     #ifndef SKIP_ERROR_HANDLING
  1124.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  1125.     #endif
  1126.     lua_pushboolean(L, src->isPlaying);
  1127.     return 1;
  1128. }
  1129.  
  1130. static int lua_soundend(lua_State *L)
  1131. {
  1132.     int argc = lua_gettop(L);
  1133.     if (argc != 0) return luaL_error(L, "wrong number of arguments");
  1134.     if (isCSND){
  1135.         CSND_shutdown();
  1136.         isCSND = false;
  1137.     }
  1138.     return 0;
  1139. }
  1140.  
  1141. static int lua_regsound(lua_State *L)
  1142. {
  1143.     int argc = lua_gettop(L);
  1144.     if (argc != 1) return luaL_error(L, "wrong number of arguments");
  1145.     u32 time = luaL_checkinteger(L, 1);
  1146.     u32 mem_size = (time + 1) * 32000; // time + 1 because first second is mute
  1147.     u8* audiobuf = (u8*)linearAlloc(mem_size);
  1148.     u32 audiobuf_pos = 0;
  1149.     u32* sharedmem = (u32*)memalign(0x1000, (0x8000) * (time + 1));
  1150.     MIC_Initialize(sharedmem, (0x8000) * (time + 1), 0x40, 0, 3, 1, 1);
  1151.     MIC_SetRecording(1);
  1152.     u64 startRegister = osGetTime();
  1153.     while ((osGetTime() - startRegister) <= ((time + 1) * 1000)){
  1154.     audiobuf_pos+= MIC_ReadAudioData(&audiobuf[audiobuf_pos], mem_size-audiobuf_pos, 1);
  1155.     }
  1156.     MIC_SetRecording(0);
  1157.     MIC_Shutdown();
  1158.     free(sharedmem);
  1159.    
  1160.     //Prevent first mute second to be allocated in wav struct
  1161.     u8* nomute_audiobuf =  (u8*)linearAlloc(mem_size - 32000);
  1162.     memcpy(nomute_audiobuf,&audiobuf[32000],mem_size - 32000);
  1163.     linearFree(audiobuf);
  1164.    
  1165.     wav* wav_file = (wav*)malloc(sizeof(wav));
  1166.     wav_file->audiobuf = nomute_audiobuf;
  1167.     wav_file->audiobuf2 = NULL;
  1168.     wav_file->big_endian = false;
  1169.     wav_file->mem_size = 0;
  1170.     wav_file->size = mem_size - 32000;
  1171.     wav_file->samplerate = 16000;
  1172.     strcpy(wav_file->author,"");
  1173.     strcpy(wav_file->title,"");
  1174.     wav_file->isPlaying = false;
  1175.     wav_file->bytepersample = 2;
  1176.     lua_pushinteger(L,(u32)wav_file);
  1177.     return 1;
  1178. }
  1179.  
  1180. static int lua_savemono(lua_State *L)
  1181. {
  1182.     int argc = lua_gettop(L);
  1183.     if (argc != 2) return luaL_error(L, "wrong number of arguments");
  1184.     wav* src = (wav*)luaL_checkinteger(L, 1);
  1185.     #ifndef SKIP_ERROR_HANDLING
  1186.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  1187.     #endif
  1188.     const char* file = luaL_checkstring(L, 2);
  1189.     Handle fileHandle;
  1190.     u32 bytesWritten;
  1191.     FS_archive sdmcArchive=(FS_archive){ARCH_SDMC, (FS_path){PATH_EMPTY, 1, (u8*)""}};
  1192.     FS_path filePath=FS_makePath(PATH_CHAR, file);
  1193.     FSUSER_OpenFileDirectly(NULL, &fileHandle, sdmcArchive, filePath, FS_OPEN_CREATE|FS_OPEN_WRITE, FS_ATTRIBUTE_NONE);
  1194.     u32 four_bytes;
  1195.     u16 two_bytes;
  1196.     FSFILE_Write(fileHandle, &bytesWritten, 0, "RIFF", 4, FS_WRITE_FLUSH);
  1197.     four_bytes = src->size + 36;
  1198.     FSFILE_Write(fileHandle, &bytesWritten, 4, &four_bytes, 8, FS_WRITE_FLUSH);
  1199.     FSFILE_Write(fileHandle, &bytesWritten, 8, "WAVEfmt ", 8, FS_WRITE_FLUSH);
  1200.     four_bytes = 16;
  1201.     FSFILE_Write(fileHandle, &bytesWritten, 16, &four_bytes, 4, FS_WRITE_FLUSH);
  1202.     FSFILE_Write(fileHandle, &bytesWritten, 20, &(src->encoding), 2, FS_WRITE_FLUSH);
  1203.     FSFILE_Write(fileHandle, &bytesWritten, 22, &two_bytes, 2, FS_WRITE_FLUSH);
  1204.     FSFILE_Write(fileHandle, &bytesWritten, 24, &(src->samplerate), 4, FS_WRITE_FLUSH);
  1205.     four_bytes = src->samplerate * src->bytepersample;
  1206.     FSFILE_Write(fileHandle, &bytesWritten, 28, &four_bytes, 4, FS_WRITE_FLUSH);
  1207.     two_bytes = src->bytepersample*8;
  1208.     FSFILE_Write(fileHandle, &bytesWritten, 32, &(src->bytepersample), 2, FS_WRITE_FLUSH);
  1209.     FSFILE_Write(fileHandle, &bytesWritten, 34, &two_bytes, 2, FS_WRITE_FLUSH);
  1210.     FSFILE_Write(fileHandle, &bytesWritten, 36, "data", 4, FS_WRITE_FLUSH);
  1211.     FSFILE_Write(fileHandle, &bytesWritten, 40, &(src->size), 4, FS_WRITE_FLUSH);
  1212.     FSFILE_Write(fileHandle, &bytesWritten, 44, src->audiobuf, src->size, FS_WRITE_FLUSH);
  1213.     FSFILE_Close(fileHandle);
  1214.     svcCloseHandle(fileHandle);
  1215.     return 0;
  1216. }
  1217.  
  1218. static int lua_getSrate(lua_State *L){
  1219. int argc = lua_gettop(L);
  1220.     if (argc != 1) return luaL_error(L, "wrong number of arguments");
  1221.     wav* src = (wav*)luaL_checkinteger(L, 1);
  1222.     #ifndef SKIP_ERROR_HANDLING
  1223.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  1224.     #endif
  1225.     lua_pushinteger(L, src->samplerate);
  1226.     return 1;
  1227. }
  1228.  
  1229. static int lua_getTime(lua_State *L){
  1230. int argc = lua_gettop(L);
  1231.     if (argc != 1) return luaL_error(L, "wrong number of arguments");
  1232.     wav* src = (wav*)luaL_checkinteger(L, 1);
  1233.     #ifndef SKIP_ERROR_HANDLING
  1234.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  1235.     #endif
  1236.     if (src->isPlaying){
  1237.         lua_pushinteger(L, (osGetTime() - src->tick) / 1000);
  1238.     }else{
  1239.         lua_pushinteger(L, src->tick / 1000);
  1240.     }
  1241.     return 1;
  1242. }
  1243.  
  1244. static int lua_getTotalTime(lua_State *L){
  1245. int argc = lua_gettop(L);
  1246.     if (argc != 1) return luaL_error(L, "wrong number of arguments");
  1247.     wav* src = (wav*)luaL_checkinteger(L, 1);
  1248.     #ifndef SKIP_ERROR_HANDLING
  1249.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  1250.     #endif
  1251.     if ((src->encoding == CSND_ENCODING_IMA_ADPCM) && (src->audiobuf2 != NULL) && (src->mem_size == 0)) lua_pushinteger(L,(src->size - src->startRead) / (src->samplerate / 2));
  1252.     else if ((src->audiobuf2 != NULL) && (src->mem_size == 0)) lua_pushinteger(L,((src->size*2) - src->startRead) / (src->bytepersample * src->samplerate));
  1253.     else lua_pushinteger(L,(src->size - src->startRead) / ((src->bytepersample) * src->samplerate));
  1254.     return 1;
  1255. }
  1256.  
  1257. static int lua_getTitle(lua_State *L){
  1258. int argc = lua_gettop(L);
  1259.     if (argc != 1) return luaL_error(L, "wrong number of arguments");
  1260.     wav* src = (wav*)luaL_checkinteger(L, 1);
  1261.     #ifndef SKIP_ERROR_HANDLING
  1262.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  1263.     #endif
  1264.     lua_pushstring(L, src->title);
  1265.     return 1;
  1266. }
  1267.  
  1268. static int lua_getAuthor(lua_State *L){
  1269. int argc = lua_gettop(L);
  1270.     if (argc != 1) return luaL_error(L, "wrong number of arguments");
  1271.     wav* src = (wav*)luaL_checkinteger(L, 1);
  1272.     #ifndef SKIP_ERROR_HANDLING
  1273.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  1274.     #endif
  1275.     lua_pushstring(L, src->author);
  1276.     return 1;
  1277. }
  1278.  
  1279. static int lua_getType(lua_State *L){
  1280. int argc = lua_gettop(L);
  1281.     if (argc != 1) return luaL_error(L, "wrong number of arguments");
  1282.     wav* src = (wav*)luaL_checkinteger(L, 1);
  1283.     #ifndef SKIP_ERROR_HANDLING
  1284.         if (src->magic != 0x4C534E44) return luaL_error(L, "attempt to access wrong memory block type");
  1285.     #endif
  1286.     if (src->audiobuf2 == NULL) lua_pushinteger(L, 1);
  1287.     else lua_pushinteger(L, 2);
  1288.     return 1;
  1289. }
  1290.  
  1291. //Register our Sound Functions
  1292. static const luaL_Reg Sound_functions[] = {
  1293.   {"openOgg",               lua_openogg},
  1294.   {"openWav",               lua_openwav},
  1295.   {"openAiff",              lua_openaiff},
  1296.   {"close",                 lua_closeWav},
  1297.   {"play",                  lua_playWav},
  1298.   {"init",                  lua_soundinit},
  1299.   {"term",                  lua_soundend},
  1300.   {"pause",                 lua_pause},
  1301.   {"getSrate",              lua_getSrate},
  1302.   {"getTime",               lua_getTime},
  1303.   {"getTitle",              lua_getTitle},
  1304.   {"getAuthor",             lua_getAuthor},
  1305.   {"getType",               lua_getType},  
  1306.   {"getTotalTime",          lua_getTotalTime},
  1307.   {"resume",                lua_resume},
  1308.   {"isPlaying",             lua_wisPlaying},
  1309.   {"register",              lua_regsound},
  1310.   {"saveWav",               lua_savemono},
  1311.   {0, 0}
  1312. };
  1313.  
  1314. void luaSound_init(lua_State *L) {
  1315.     lua_newtable(L);
  1316.     luaL_setfuncs(L, Sound_functions, 0);
  1317.     lua_setglobal(L, "Sound");
  1318. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement