Advertisement
Kitomas

bytebeat demo using winmm

May 31st, 2024
503
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.53 KB | None | 0 0
  1. //compile with:
  2.  //"cl tiny_bytebeat.cpp kernel32.lib /GS- /Os /link /entry:main /SUBSYSTEM:WINDOWS /NODEFAULTLIB"
  3. //("/GS-" to disable buffer security check, since it seems to break when not using crt)
  4.  
  5.  
  6. //#define WIN32_LEAN_AND_MEAN
  7. #include <Windows.h>
  8. #include <mmsystem.h>
  9.  
  10.  
  11.  
  12. #define _PI2 1.57079632679489661923f
  13. #define _PI  3.14159265358979323846f
  14. #define _2PI 6.28318530717958647692f
  15.  
  16. #define lengthof(_thing, _type) (sizeof(_thing)/sizeof(_type))
  17.  
  18. //doing "*((FARPROC*)&_name)" to work around not
  19.  //being able to directly cast an lvalue
  20. #define LOAD_FUNC(_strname, _name, _dll) \
  21.   *((FARPROC*)&_name) = GetProcAddress(_dll, _strname)
  22.  
  23.  
  24.  
  25. typedef unsigned char      u8;
  26. typedef unsigned short     u16;
  27. typedef unsigned int       u32;
  28. typedef unsigned long long u64;
  29.  
  30. typedef signed char      s8;
  31. typedef signed short     s16;
  32. typedef signed int       s32;
  33. typedef signed long long s64;
  34.  
  35. typedef float  f32;
  36. typedef double f64;
  37.  
  38.  
  39.  
  40. //"tiny.obj : error LNK2001: unresolved external symbol _fltused"
  41.  //(i think this is because i'm not using the crt)
  42. #ifdef __cplusplus
  43. extern "C" {
  44. #endif
  45. char _fltused = 0; //this works lmaooo
  46. #ifdef __cplusplus
  47. }
  48. #endif
  49.  
  50.  
  51.  
  52. /*******************************************************************************/
  53.  
  54.  
  55.  
  56. HMODULE _User32_dll;
  57. HMODULE _winmm_dll;
  58.  
  59.  
  60.  
  61. //User32
  62. #define MessageBoxA MessageBoxA_
  63.  
  64. int (WINAPI *MessageBoxA_)(HWND, LPCSTR, LPCSTR, UINT);
  65.  
  66.  
  67.  
  68. //winmm
  69. #define waveOutGetNumDevs      winmm.waveOutGetNumDevs_
  70. #define waveOutGetDevCapsA     winmm.waveOutGetDevCapsA_
  71. #define waveOutGetVolume       winmm.waveOutGetVolume_
  72. #define waveOutSetVolume       winmm.waveOutSetVolume_
  73. #define waveOutGetErrorTextA   winmm.waveOutGetErrorTextA_
  74. #define waveOutOpen            winmm.waveOutOpen_
  75. #define waveOutClose           winmm.waveOutClose_
  76. #define waveOutPrepareHeader   winmm.waveOutPrepareHeader_
  77. #define waveOutUnprepareHeader winmm.waveOutUnprepareHeader_
  78. #define waveOutWrite           winmm.waveOutWrite_
  79. #define waveOutPause           winmm.waveOutPause_
  80. #define waveOutRestart         winmm.waveOutRestart_
  81. #define waveOutReset           winmm.waveOutReset_
  82. #define waveOutBreakLoop       winmm.waveOutBreakLoop_
  83. #define waveOutGetPosition     winmm.waveOutGetPosition_
  84. #define waveOutGetPitch        winmm.waveOutGetPitch_
  85. #define waveOutSetPitch        winmm.waveOutSetPitch_
  86. #define waveOutGetPlaybackRate winmm.waveOutGetPlaybackRate_
  87. #define waveOutSetPlaybackRate winmm.waveOutSetPlaybackRate_
  88. #define waveOutGetID           winmm.waveOutGetID_
  89. #define waveOutMessage         winmm.waveOutMessage_
  90.  
  91. #define winmm_strlength 21
  92. #define winmm_names_len (lengthof(winmm_names, char)/winmm_strlength)
  93. char winmm_names[][winmm_strlength] = {
  94.                           //(not including null terminator)
  95. //"waveOutGetNumDevs",      //length = [17]
  96. //"waveOutGetDevCapsA",     //length = [18]
  97. //"waveOutGetVolume",       //length = [16]
  98. "waveOutSetVolume",       //length = [16]
  99. //"waveOutGetErrorTextA",   //length = [20]
  100. "waveOutOpen",            //length = [11]
  101. //"waveOutClose",           //length = [12]
  102. "waveOutPrepareHeader",   //length = [20]
  103. //"waveOutUnprepareHeader", //length = [22]
  104. "waveOutWrite",           //length = [12]
  105. "waveOutPause",           //length = [12]
  106. //"waveOutRestart",         //length = [14]
  107. //"waveOutReset",           //length = [12]
  108. //"waveOutBreakLoop",       //length = [16]
  109. //"waveOutGetPosition",     //length = [18]
  110. //"waveOutGetPitch",        //length = [15]
  111. //"waveOutSetPitch",        //length = [15]
  112. //"waveOutGetPlaybackRate", //length = [22]
  113. //"waveOutSetPlaybackRate", //length = [22]
  114. //"waveOutGetID",           //length = [12]
  115. //"waveOutMessage",         //length = [14]
  116. };
  117.  
  118.  
  119. union winmm_func {
  120.   FARPROC _FUNCTIONS[winmm_names_len];
  121.  
  122.   struct {
  123.     //UINT     (WINAPI *waveOutGetNumDevs_)(void);
  124.     //MMRESULT (WINAPI *waveOutGetDevCapsA_)(UINT_PTR, LPWAVEOUTCAPSA, UINT);
  125.     //MMRESULT (WINAPI *waveOutGetVolume_)(HWAVEOUT, LPDWORD);
  126.     MMRESULT (WINAPI *waveOutSetVolume_)(HWAVEOUT, DWORD);
  127.     //MMRESULT (WINAPI *waveOutGetErrorTextA_)(MMRESULT, LPSTR, UINT);
  128.     MMRESULT (WINAPI *waveOutOpen_)(LPHWAVEOUT, UINT, LPCWAVEFORMATEX, DWORD_PTR, DWORD_PTR, DWORD);
  129.     //MMRESULT (WINAPI *waveOutClose_)(HWAVEOUT);
  130.     MMRESULT (WINAPI *waveOutPrepareHeader_)(HWAVEOUT, LPWAVEHDR, UINT);
  131.     //MMRESULT (WINAPI *waveOutUnprepareHeader_)(HWAVEOUT, LPWAVEHDR, UINT);
  132.     MMRESULT (WINAPI *waveOutWrite_)(HWAVEOUT, LPWAVEHDR, UINT);
  133.     MMRESULT (WINAPI *waveOutPause_)(HWAVEOUT);
  134.     //MMRESULT (WINAPI *waveOutRestart_)(HWAVEOUT);
  135.     //MMRESULT (WINAPI *waveOutReset_)(HWAVEOUT);
  136.     //MMRESULT (WINAPI *waveOutBreakLoop_)(HWAVEOUT);
  137.     //MMRESULT (WINAPI *waveOutGetPosition_)(HWAVEOUT, LPMMTIME, UINT);
  138.     //MMRESULT (WINAPI *waveOutGetPitch_)(HWAVEOUT, LPDWORD);
  139.     //MMRESULT (WINAPI *waveOutSetPitch_)(HWAVEOUT, DWORD);
  140.     //MMRESULT (WINAPI *waveOutGetPlaybackRate_)(HWAVEOUT, LPDWORD);
  141.     //MMRESULT (WINAPI *waveOutSetPlaybackRate_)(HWAVEOUT, DWORD);
  142.     //MMRESULT (WINAPI *waveOutGetID_)(HWAVEOUT, LPUINT);
  143.     //MMRESULT (WINAPI *waveOutMessage_)(HWAVEOUT, UINT, DWORD_PTR, DWORD_PTR);
  144.   };
  145. };
  146.  
  147. winmm_func winmm;
  148.  
  149.  
  150.  
  151.  
  152. static inline void LOAD_FUNC_ALL(){
  153.   _User32_dll = LoadLibrary("User32.dll");
  154.   _winmm_dll  = LoadLibrary("winmm.dll");
  155.  
  156.   LOAD_FUNC("MessageBoxA",  MessageBoxA_, _User32_dll);
  157.  
  158.   for(u32 i=0; i<winmm_names_len; ++i)
  159.     winmm._FUNCTIONS[i] = GetProcAddress(_winmm_dll, winmm_names[i]);
  160. }
  161.  
  162.  
  163.  
  164. /*******************************************************************************/
  165.  
  166.  
  167.  
  168. #define SAMPLERATE 11025
  169. #define _chunk_count 3
  170. #define _chunk_samples 512
  171.  
  172. s16     _chunk_data[_chunk_count][_chunk_samples];
  173. WAVEHDR _chunk_header[_chunk_count];
  174. int _chunk_which;
  175. HWAVEOUT wave_out;
  176.  
  177. void audio_callback(s16* smp, u32 len);
  178.  
  179.  
  180.  
  181. void CALLBACK WaveOutProc(HWAVEOUT hwo, UINT msg, DWORD_PTR inst,
  182.                           DWORD_PTR param1, DWORD_PTR param2)
  183. {
  184.   if(msg == WOM_DONE){
  185.     audio_callback(_chunk_data[_chunk_which], _chunk_samples);
  186.     waveOutWrite(hwo, &_chunk_header[_chunk_which], sizeof(WAVEHDR));
  187.     _chunk_which = (_chunk_which+1)%_chunk_count;
  188.   }
  189.  
  190. }
  191.  
  192.  
  193.  
  194. static inline bool WaveOutInit(){
  195.   _chunk_which = 0;
  196.  
  197.   WAVEFORMATEX fmt;
  198.   fmt.wFormatTag     = WAVE_FORMAT_PCM;
  199.   fmt.nChannels      =  1;
  200.   fmt.nSamplesPerSec = SAMPLERATE;
  201.   fmt.wBitsPerSample = 16;
  202.   fmt.cbSize         =  0;
  203.  
  204.   fmt.nBlockAlign     = fmt.nChannels      * fmt.wBitsPerSample / 8;
  205.   fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
  206.  
  207.   if(waveOutOpen(&wave_out, WAVE_MAPPER, &fmt,
  208.                  (DWORD_PTR)WaveOutProc, 0, CALLBACK_FUNCTION))
  209.   {
  210.     return false;
  211.   }
  212.  
  213.   #define WO_VOLUME(_left, _right) ( ((_right)<<16) | (_left) )
  214.   if(waveOutSetVolume(wave_out, WO_VOLUME(0xffff, 0xffff) )) return false;
  215.  
  216.   //set header info and prime the audio buffers
  217.   for(u32 i=0; i<_chunk_count; ++i){
  218.     _chunk_header[i].lpData          = (CHAR*)_chunk_data[i];
  219.     _chunk_header[i].dwBufferLength  = _chunk_samples*sizeof(s16)*fmt.nChannels;
  220.     _chunk_header[i].dwBytesRecorded = 0;
  221.     _chunk_header[i].dwUser          = 0;
  222.     _chunk_header[i].dwFlags         = 0;
  223.     _chunk_header[i].dwLoops         = 0;
  224.     _chunk_header[i].lpNext          = nullptr;
  225.     _chunk_header[i].reserved        = 0;
  226.  
  227.     if(waveOutPrepareHeader(wave_out, &_chunk_header[i], sizeof(WAVEHDR)))
  228.       return false;
  229.  
  230.     audio_callback(_chunk_data[i], _chunk_samples);
  231.     if(waveOutWrite(wave_out, &_chunk_header[i], sizeof(WAVEHDR)))
  232.       return false;
  233.  
  234.   }
  235.  
  236.   return true;
  237. }
  238.  
  239.  
  240.  
  241. /*******************************************************************************/
  242.  
  243.  
  244.  
  245. #define volume 0.05f
  246. #define u8_smp(_smp) (  (s16)( ((_smp)-128)<<8 )  ) //u8 to s16 sample
  247. void audio_callback(s16* smp, u32 len){
  248.   static s64 t = 0;
  249.  
  250.   for(u32 i=0; i<len; ++i){
  251.     //bytebeat shamelessly stolen from dollchan (go check out their bytebeat editor, seriously)
  252.     smp[i] = u8_smp( (((t/10|0)^(t/10|0)-1280)%11*t/2&127)+(((t/640|0)^(t/640|0)-2)%13*t/2&127) );
  253.     smp[i] *= volume;
  254.     ++t;
  255.  
  256.   }
  257.  
  258. }
  259.  
  260.  
  261. int main(){
  262.   int returnCode = 0;
  263.  
  264.   LOAD_FUNC_ALL();
  265.   if(!WaveOutInit()){
  266.     MessageBoxA(nullptr, "failed to initialize audio device", "oh no!", MB_ICONERROR);
  267.     --returnCode; goto _quit_;
  268.  
  269.   }
  270.  
  271.   MessageBoxA(nullptr, "cool bytebeat", "cool message box", MB_OK);
  272.   //Sleep(2000);
  273.   waveOutPause(wave_out);
  274.  
  275.   _quit_:
  276.   //program hangs unless i explicitly exit the process for some reason
  277.   ExitProcess((UINT)returnCode);
  278.   return returnCode;
  279. }
  280.  
  281.  
  282.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement