Advertisement
Kitomas

2024-07-19 (0/13)

Jul 19th, 2024
190
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 28.14 KB | None | 0 0
  1. /******************************************************************************/
  2. /******************************************************************************/
  3. //"kit_w32\src\main.cpp":
  4. #include <kit/all.hpp>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <math.h>
  8.  
  9.  
  10. #include "test_main_utils.hpp"
  11.  
  12.  
  13. using namespace kit;
  14.  
  15. //get random 64-bit float value from 0.0 -> 1.0
  16. f64 drand(){
  17.   u32 value = ((u32)rand())<<15 | rand();
  18.   return (f64)value/(KIT_U32_MAX>>2);
  19. }
  20.  
  21.  
  22. #define canvasX 256
  23. #define canvasY 144
  24. Window* win;
  25.  
  26.  
  27. char buffer[4096];
  28. size_t numChars = 0;
  29.  
  30.  
  31. shape::point points[] = {
  32.   {  4,  5},
  33.   { 50, 50},
  34.   {150, 50},
  35.   { 25,  2},
  36. };
  37.  
  38.  
  39. shape::rect rects[] = {
  40.   {1,10, 5,5},
  41.   {3,30, 4,4},
  42. };
  43.  
  44.  
  45.  
  46.  
  47.  
  48. struct f32_stereo { float l,r; };
  49. int t=0;
  50.  
  51. s32 callback(const void* _inBuffer, void* _outBuffer,
  52.              const AudioStreamInfo* info, void* userdata)
  53. {
  54.   (void)_inBuffer; //unused
  55.   (void)userdata;   //
  56.   f32_stereo* outBuffer = (f32_stereo*)_outBuffer;
  57.   s32 sampleRate = (s32)info->sampleRate;
  58.   u32 numSamples = info->sampleFrames;
  59.  
  60.   for(u32 i=0; i<numSamples; ++i){
  61.     outBuffer[i].l = sinf(((f32)(t++)/sampleRate)*3.14159f*2*440)*0.5f;
  62.  
  63.     outBuffer[i].r = outBuffer[i].l;
  64.   }
  65.  
  66.   return ASTREAM_RTN_CONTINUE;
  67. }
  68.  
  69.  
  70.  
  71.  
  72. s32 threadFunc(void* userdata){
  73.   printf("start of func\n");
  74.   time::sleep(500);
  75.   printf("end of func\n");
  76.   return -2;
  77. }
  78.  
  79.  
  80.  
  81. f64 sleepTest(u32 ms){
  82.   u64 ticksStart = time::getTicks();
  83.   time::sleep(ms);
  84.   u64 ticksDelta = time::getTicks()-ticksStart;
  85.   return (f64)ticksDelta/time::getTicksPerSecond();
  86. }
  87.  
  88. u32 profileFrameSleep(){
  89.   f64 closestValue = 0.1,  smallestDifference = 1.0;
  90.  
  91.   for(int i=9; i<17; ++i){
  92.     f64 result = ( sleepTest(i) + sleepTest(i) + sleepTest(i) ) / 3;
  93.     f64 currentDifference = fabs(result-0.01667);
  94.  
  95.     if(currentDifference < smallestDifference){
  96.       smallestDifference = currentDifference;
  97.       closestValue = result;
  98.  
  99.     }
  100.   }
  101.  
  102.   return (u32)(closestValue*1000);
  103. }
  104.  
  105.  
  106.  
  107.  
  108. f32 scale = 1.0f;
  109. shape::point pos(0,0);
  110. int main(int argc, char** argv){ try {
  111.   //seed rng
  112.   srand(time::getTicks()&KIT_U32_MAX);
  113.  
  114.  
  115.   //create window
  116.   win = new Window("cool snake game", //window title
  117.                    1280, 720,         //initial window size
  118.                    WINFLAG_RESIZABLE, //window capability flags
  119.                    WINPOS_CENTERED,   //window x position
  120.                    WINPOS_CENTERED,   //window y position
  121.                    0, 0,  //canvas size
  122.                    true);            //'can pixels be accessed directly?'
  123.   //win->setVisibility(true);
  124.  
  125.   //Bitmap bmp(ball, 8,8, win, false);
  126.   Bitmap bmp("mass.qoi", win);
  127.   bmp.setBlitDestination(win);
  128.  
  129.   win->setCanvasSize(canvasX,canvasY);
  130.  
  131.   FStr _fstr(2048);
  132.   BitmapFont pico8("_fontPico8.qoi", win);
  133.   BitmapFont text("_font8x8.qoi", win);
  134.   buffer[0] = 0;
  135.   #define pico8f(_x,_y, _fmt,...) pico8.print((_y),(_y), _fstr.fmt(_fmt,__VA_ARGS__), 0)
  136.   #define textf(_x,_y, _fmt,...) text.print((_y),(_y), _fstr.fmt(_fmt,__VA_ARGS__) , 0)
  137.  
  138.   TimerSimple frameTimer;
  139.  
  140.  
  141.   //run loop
  142.   bool run = true,  fullscreen = false;
  143.   _before_loop:
  144.   while(run){
  145.     u64 startTicks = time::getTicks();
  146.     frameTimer.setTimer(0.001);
  147.  
  148.     //process events in event queue
  149.     WindowEvent event;
  150.     while(pollWindowEvent(&event)){
  151.       //printEvent(event);
  152.       switch(event.type){
  153.         case WINEVENT_WIN_CLOSE: run = false; goto _before_loop;
  154.         case WINEVENT_KEY_DOWN:
  155.         {
  156.           switch(event.key.vkey){
  157.             case VKEY_ESCAPE: run = false; goto _before_loop;
  158.             case VKEY_F11   : fullscreen ^= 1; win->setFullscreen(fullscreen); break;
  159.             case VKEY_UP    : scale += 0.125f; break;
  160.             case VKEY_DOWN  : scale -= 0.125f; break;
  161.             case VKEY_LEFT  : pos.y -= 1; break;
  162.             case VKEY_RIGHT : pos.y += 1; break;
  163.           }
  164.         } break;
  165.  
  166.         case WINEVENT_KEY_CHAR:
  167.         {
  168.           if(event.key.vkey == VKEY_ENTER){
  169.             buffer[(numChars++)&4095] = '\n';
  170.           } else if(event.key.vkey == '\b'){
  171.             buffer[(--numChars)&4095] = 0;
  172.           } else {
  173.             buffer[(numChars++)&4095] = event.key.vkey;
  174.           }
  175.           if(numChars > 4095) numChars = 0;
  176.  
  177.         } break;
  178.       }
  179.     }
  180.  
  181.     win->clear(0x007f007f);
  182.  
  183.     bmp.blit(pos.x,pos.y, scale);
  184.     win->drawRectangles(rects, 2, 0x00007f);
  185.     text.setScale(scale,scale);
  186.     text.print(1,1,buffer);
  187.     //pico8.print(1,1,buffer);
  188.     //pico8f(1,40,"test %u",4);
  189.     win->drawLines(points, 4, 0x0000ff, 5);
  190.     win->drawPoints(points,sizeof(points)/sizeof(shape::point), 0x0000ff, false);
  191.     win->drawPoint({0,0}, 0x0000ff);
  192.  
  193.  
  194.     win->present();
  195.  
  196.  
  197.     //time::sleep(10);
  198.     frameTimer.wait();
  199.     //printf("%f\n",(f64)(time::getTicks()-startTicks)/10000);
  200.   }
  201.  
  202.   delete win;
  203.  
  204.  
  205.   s32* a = nullptr;
  206.   if(!memory::realloc(&a, sizeof(s32))) return -2;
  207.   *a = 5;
  208.   printf("a = %p, *a = %i\n", a, *a);
  209.   if(!memory::realloc(&a, sizeof(s32)*2)) return -2;
  210.   a[1] = 3;
  211.   printf("a = %p, a[0] = %i, a[1] = %i\n", a, a[0], a[1]);
  212.   memory::free(&a);
  213.  
  214. /*
  215.   Thread testThread(threadFunc, nullptr, true);
  216.  
  217.   AudioStream stream(callback,nullptr,2048);
  218.   stream.start();
  219.   time::sleep(1001);
  220.   stream.stop();
  221.   time::sleep(100);
  222. */
  223.  
  224.   printf("%llu,",memory::getNumAllocations());
  225.   MutexSimple* mutex = new MutexSimple;
  226.   printf("%llu,",memory::getNumAllocations());
  227.   delete mutex;
  228.   printf("%llu\n",memory::getNumAllocations());
  229.  
  230.  
  231.   return 0;
  232.  
  233. } catch(const char* errorText){
  234. #ifdef _DEBUG
  235.   printf("FATAL EXCEPTION OCCURRED!: \"%s\"\n",errorText);
  236. #else
  237.   showMessageBox(errorText,"FATAL EXCEPTION OCCURRED!", MSGBOX_ICN_ERROR);
  238. #endif /* _DEBUG */
  239.   return -1;
  240. }}
  241. /******************************************************************************/
  242. /******************************************************************************/
  243. //"kit_w32\src\kit_win32\kit_AudioStream.cpp":
  244. #include "_kit_common_shared.hpp"
  245.  
  246. #define KIT_INVALID_AUDIOSTREAM _kit_invalid_audiostream
  247.  
  248. #define KIT_IS_INVALID_AUDIOSTREAM (!_valid && !_constructing)
  249.  
  250.  
  251. namespace kit {
  252.  
  253. static const char _kit_invalid_audiostream[] = "invalid audio stream";
  254.  
  255.  
  256.  
  257.  
  258. int _AudioStream_PaCallback(const void* inBuffer, void* outBuffer, u32 smpFrames,
  259.                             const PaStreamCallbackTimeInfo* timeInfo,
  260.                             PaStreamCallbackFlags statusFlags, void* userdata)
  261. {
  262.   (void)statusFlags; //these are left unused
  263.   AudioStream* stream = (AudioStream*)userdata;
  264.   if(!KIT_IS_CLASS_VALID(stream)) return paAbort;
  265.  
  266.   _AudioStreamOpaque* opq = (_AudioStreamOpaque*)KIT_GET_CLASS_OPAQUE(stream);
  267.   if(opq == nullptr) return paAbort;
  268.  
  269.   stream->lock(true);
  270.  
  271.  
  272.   //update relevant values in stream info
  273.   AudioStreamInfo* info = &opq->astreamInfo;
  274.  
  275.   info->timeInput   = timeInfo->inputBufferAdcTime;
  276.   info->timeCurrent = timeInfo->currentTime;
  277.   info->timeOutput  = timeInfo->outputBufferDacTime;
  278.  
  279.   if(info->inputDeviceID != -1){
  280.     info->inputBufferSize = smpFrames * info->inputChannels *
  281.                             KIT_ASTREAM_FMT_BYTESIZE(info->inputFormat);
  282.   }
  283.  
  284.   if(info->outputDeviceID != -1){
  285.     info->outputBufferSize = smpFrames * info->outputChannels *
  286.                              KIT_ASTREAM_FMT_BYTESIZE(info->inputFormat);
  287.   }
  288.  
  289.   info->sampleFrames = smpFrames;
  290.  
  291.  
  292.   int result = paAbort;
  293.   if(opq->callback != nullptr){
  294.     result = opq->callback(inBuffer, outBuffer, &opq->astreamInfo, opq->userdata);
  295.   }
  296.  
  297.  
  298.   stream->lock(false);
  299.  
  300.   return result;
  301. }
  302.  
  303.  
  304.  
  305.  
  306. void _AudioStream_PaFinishedCallback(void* userdata){
  307.   AudioStream* stream = (AudioStream*)userdata;
  308.   if(!KIT_IS_CLASS_VALID(stream)) return;
  309.  
  310.   _AudioStreamOpaque* opq = (_AudioStreamOpaque*)KIT_GET_CLASS_OPAQUE(stream);
  311.   if(opq == nullptr) return;
  312.  
  313.   stream->lock(true);
  314.   if(opq->endCallback != nullptr) opq->endCallback(opq->userdata);
  315.   stream->lock(false);
  316. }
  317.  
  318.  
  319.  
  320.  
  321. void AudioStream::_construct(const AudioStreamParams* params){
  322.   _type = KIT_CLASSTYPE_AUDIOSTREAM;
  323.  
  324.   if(params == nullptr)
  325.     throw "params = nullptr";
  326.   if(params->inputDeviceID == -1  &&  params->outputDeviceID == -1)
  327.     throw "no device ID was given";
  328.   if(params->callback == nullptr)
  329.     throw "callback cannot be nullptr";
  330.  
  331.  
  332.   _opq = (_AudioStreamOpaque*)memory::alloc(sizeof(_AudioStreamOpaque));
  333.   if(_opq == nullptr) throw "ran out of memory creating _opq";
  334.   memory::set(_opq, 0, sizeof(_AudioStreamOpaque));
  335.  
  336.   const char* errorText = nullptr;
  337.   if(0){ //entered in the event of an exception
  338.     //(deleting critical section is not necessary, since creation of it will
  339.      //never fail, and it's the last thing to initialize anyway)
  340.     //_DelCritSect: DeleteCriticalSection(&_opq->lock);
  341.     _CloseStream: Pa_CloseStream(_opq->streamPtr);
  342.     _FreeOpaque : memory::free(&_opq);
  343.     throw errorText;
  344.   }
  345.  
  346.  
  347.  
  348.   _opq->callback = params->callback;
  349.   _opq->userdata = params->userdata;
  350.  
  351.  
  352.   //input parameters
  353.   PaStreamParameters* inParams = nullptr;
  354.   f64 inDefSmpRate = -1.0;
  355.   if(params->inputDeviceID > -1){
  356.     inParams = &_opq->streamInputParams;
  357.     inParams->device           = params->inputDeviceID;
  358.     inParams->channelCount     = params->inputChannels;
  359.     inParams->sampleFormat     = ConvertToPaSampleFormat(params->inputFormat);
  360.     inParams->suggestedLatency = params->inputSuggestedLatency;
  361.  
  362.     if(inParams->sampleFormat == paCustomFormat){
  363.       errorText = "invalid input sample format";
  364.       goto _FreeOpaque;
  365.     }
  366.  
  367.  
  368.     const PaDeviceInfo* inDevInfo = Pa_GetDeviceInfo(inParams->device);
  369.     if(inDevInfo == nullptr){
  370.       errorText = "invalid input device ID";
  371.       goto _FreeOpaque;
  372.     }
  373.  
  374.     inDefSmpRate = inDevInfo->defaultSampleRate;
  375.  
  376.     if(inParams->channelCount < 0)
  377.       inParams->channelCount = MIN(2, inDevInfo->maxInputChannels);
  378.  
  379.     if(inParams->suggestedLatency < 0.0)
  380.       inParams->suggestedLatency = inDevInfo->defaultHighInputLatency;
  381.   }
  382.  
  383.  
  384.   //output parameters
  385.   PaStreamParameters* outParams = nullptr;
  386.   f64 outDefSmpRate = -1.0;
  387.   if(params->outputDeviceID > -1){
  388.     outParams = &_opq->streamOutputParams;
  389.     outParams->device           = params->outputDeviceID;
  390.     outParams->channelCount     = params->outputChannels;
  391.     outParams->sampleFormat     = ConvertToPaSampleFormat(params->outputFormat);
  392.     outParams->suggestedLatency = params->outputSuggestedLatency;
  393.  
  394.     if(outParams->sampleFormat == paCustomFormat){
  395.       errorText = "invalid output sample format";
  396.       goto _FreeOpaque;
  397.     }
  398.  
  399.  
  400.     const PaDeviceInfo* outDevInfo = Pa_GetDeviceInfo(outParams->device);
  401.     if(outDevInfo == nullptr){
  402.       errorText = "invalid output device ID";
  403.       goto _FreeOpaque;
  404.     }
  405.  
  406.     outDefSmpRate = outDevInfo->defaultSampleRate;
  407.  
  408.     if(outParams->channelCount < 0)
  409.       outParams->channelCount = MIN(2, outDevInfo->maxOutputChannels);
  410.  
  411.     if(outParams->suggestedLatency < 0.0)
  412.       outParams->suggestedLatency = outDevInfo->defaultHighOutputLatency;
  413.   }
  414.  
  415.  
  416.   //sample rate
  417.   f64 sampleRate = params->sampleRate;
  418.  
  419.   if(sampleRate < 0.0){
  420.     if(inDefSmpRate != -1.0  &&  outDefSmpRate != -1.0){
  421.       if(inDefSmpRate != outDefSmpRate) //idk how this would happen, but just in case
  422.         throw "input and output's default sample rates are different";
  423.       sampleRate = inDefSmpRate;
  424.  
  425.     } else if(inDefSmpRate != -1.0){
  426.       sampleRate = inDefSmpRate;
  427.  
  428.     } else if(outDefSmpRate != -1.0){
  429.       sampleRate = outDefSmpRate;
  430.  
  431.     }
  432.   }
  433.  
  434.  
  435.  
  436.   PaError err = Pa_OpenStream(&_opq->streamPtr, inParams, outParams,
  437.                               sampleRate, params->sampleFrames, paNoFlag,
  438.                               (PaStreamCallback*)_AudioStream_PaCallback, this);
  439.   if(err != paNoError){
  440.     errorText = Pa_GetErrorText(err);
  441.     goto _FreeOpaque;
  442.   }
  443.  
  444.  
  445.   err = Pa_SetStreamFinishedCallback(_opq->streamPtr, _AudioStream_PaFinishedCallback);
  446.   if(err != paNoError){
  447.     errorText = Pa_GetErrorText(err);
  448.     goto _CloseStream;
  449.   }
  450.  
  451.  
  452.  
  453.   const PaStreamInfo* streamInfo = Pa_GetStreamInfo(_opq->streamPtr);
  454.   if(streamInfo == nullptr){
  455.     errorText = "failed to get stream info";
  456.     goto _CloseStream;
  457.   }
  458.  
  459.  
  460.   AudioStreamInfo* astreamInfo = &_opq->astreamInfo;
  461.  
  462.   //(time, buffer size, and sample frames are set each callback, but not here)
  463.  
  464.   astreamInfo->inputDeviceID  = params->inputDeviceID;
  465.   astreamInfo->outputDeviceID = params->outputDeviceID;
  466.  
  467.   astreamInfo->inputChannels  = ( inParams != nullptr) ?  inParams->channelCount : -1;
  468.   astreamInfo->outputChannels = (outParams != nullptr) ? outParams->channelCount : -1;
  469.  
  470.   astreamInfo->inputFormat    = params->inputFormat;
  471.   astreamInfo->outputFormat   = params->outputFormat;
  472.  
  473.   astreamInfo->sampleRate     = streamInfo->sampleRate;
  474.  
  475.   astreamInfo->inputLatency   = streamInfo->inputLatency;
  476.   astreamInfo->outputLatency  = streamInfo->outputLatency;
  477.  
  478.  
  479.  
  480.   InitializeCriticalSectionAndSpinCount(&_opq->lock, KIT_LOCK_SPINCOUNT);
  481.  
  482.  
  483.  
  484.   _valid = true;
  485.   _constructing = false;
  486. }
  487.  
  488.  
  489.  
  490. AudioStream::AudioStream(AudioStreamCallback callback, void* userdata,
  491.                          u32 sampleFrames, s32 channels)
  492. {
  493.   AudioStreamParams params;
  494.   params.callback       = callback;
  495.   params.userdata       = userdata;
  496.   params.outputDeviceID = Pa_GetDefaultOutputDevice();
  497.   params.sampleFrames   = sampleFrames;
  498.   //all other fields will be set to their defaults
  499.   _construct(&params);
  500. }
  501.  
  502.  
  503.  
  504. AudioStream::~AudioStream(){
  505.   if(!_valid) return;
  506.   _valid = false;
  507.  
  508.   if(_opq != nullptr){
  509.     Pa_AbortStream(_opq->streamPtr);
  510.     Pa_CloseStream(_opq->streamPtr);
  511.     DeleteCriticalSection(&_opq->lock);
  512.     memory::free(&_opq);
  513.   }
  514. }
  515.  
  516.  
  517.  
  518.  
  519. bool AudioStream::isActive(){
  520.   if(KIT_IS_INVALID_AUDIOSTREAM) throw KIT_INVALID_AUDIOSTREAM;
  521.   PaError active = Pa_IsStreamActive(_opq->streamPtr);
  522.   if(active < 0) throw Pa_GetErrorText(active);
  523.   return active;
  524. }
  525.  
  526.  
  527.  
  528. f64 AudioStream::getTime(){
  529.   if(KIT_IS_INVALID_AUDIOSTREAM) throw KIT_INVALID_AUDIOSTREAM;
  530.   f64 time = Pa_GetStreamTime(_opq->streamPtr);
  531.   if(time == 0) throw "failed to get stream's time";
  532.   return time;
  533. }
  534.  
  535.  
  536.  
  537. f64 AudioStream::getCPULoad(){
  538.   if(KIT_IS_INVALID_AUDIOSTREAM) throw KIT_INVALID_AUDIOSTREAM;
  539.   return Pa_GetStreamCpuLoad(_opq->streamPtr);
  540. }
  541.  
  542.  
  543.  
  544. AudioStreamInfo AudioStream::getInfo(){
  545.   if(KIT_IS_INVALID_AUDIOSTREAM) throw KIT_INVALID_AUDIOSTREAM;
  546.   lock(true);
  547.   AudioStreamInfo info = _opq->astreamInfo;
  548.   lock(false);
  549.   return info; //big ol' struct
  550. }
  551.  
  552.  
  553.  
  554.  
  555. void AudioStream::setCallback(AudioStreamCallback newCallback){
  556.   if(KIT_IS_INVALID_AUDIOSTREAM) throw KIT_INVALID_AUDIOSTREAM;
  557.   if(newCallback == nullptr) throw "newCallback = nullptr";
  558.   lock(true);
  559.   _opq->callback = newCallback;
  560.   lock(false);
  561. }
  562.  
  563.  
  564.  
  565. void AudioStream::setEndCallback(AudioStreamEndCallback newEndCallback){
  566.   if(KIT_IS_INVALID_AUDIOSTREAM) throw KIT_INVALID_AUDIOSTREAM;
  567.   lock(true);
  568.   _opq->endCallback = newEndCallback; //can be nullptr
  569.   lock(false);
  570. }
  571.  
  572.  
  573.  
  574.  
  575. void AudioStream::lock(bool locked){
  576.   if(KIT_IS_INVALID_AUDIOSTREAM) throw KIT_INVALID_AUDIOSTREAM;
  577.   if(locked) EnterCriticalSection(&_opq->lock);
  578.   else       LeaveCriticalSection(&_opq->lock);
  579. }
  580.  
  581.  
  582.  
  583.  
  584. void AudioStream::start(){
  585.   if(KIT_IS_INVALID_AUDIOSTREAM) throw KIT_INVALID_AUDIOSTREAM;
  586.   PaError err = Pa_StartStream(_opq->streamPtr);
  587.   if(err != paNoError) throw Pa_GetErrorText(err);
  588. }
  589.  
  590.  
  591.  
  592. void AudioStream::stop(){
  593.   if(KIT_IS_INVALID_AUDIOSTREAM) throw KIT_INVALID_AUDIOSTREAM;
  594.   PaError err = Pa_StopStream(_opq->streamPtr);
  595.   if(err != paNoError) throw Pa_GetErrorText(err);
  596. }
  597.  
  598.  
  599.  
  600. void AudioStream::abort(){
  601.   if(KIT_IS_INVALID_AUDIOSTREAM) throw KIT_INVALID_AUDIOSTREAM;
  602.   PaError err = Pa_AbortStream(_opq->streamPtr);
  603.   if(err != paNoError) throw Pa_GetErrorText(err);
  604. }
  605.  
  606.  
  607.  
  608.  
  609. }; /* namespace kit */
  610. /******************************************************************************/
  611. /******************************************************************************/
  612. //"kit_w32\src\kit_win32\kit_audio_func.cpp":
  613. #include "_kit_common_shared.hpp"
  614.  
  615.  
  616. namespace kit {
  617.  
  618.  
  619.  
  620.  
  621. s32 audio::getDeviceCount(){
  622.   s32 deviceCount = Pa_GetDeviceCount();
  623.   if(deviceCount < 0) throw Pa_GetErrorText(deviceCount);
  624.   return deviceCount;
  625. }
  626.  
  627.  
  628.  
  629.  
  630. s32 audio::getDefInputDevice(){
  631.   s32 defaultInputDevice = Pa_GetDefaultInputDevice();
  632.   if(defaultInputDevice < 0) throw Pa_GetErrorText(defaultInputDevice);
  633.   return defaultInputDevice;
  634. }
  635.  
  636.  
  637.  
  638. s32 audio::getDefOutputDevice(){
  639.   s32 defaultOutputDevice = Pa_GetDefaultOutputDevice();
  640.   if(defaultOutputDevice < 0) throw Pa_GetErrorText(defaultOutputDevice);
  641.   return defaultOutputDevice;
  642. }
  643.  
  644.  
  645.  
  646.  
  647. AudioDeviceInfo audio::getDeviceInfo(s32 deviceID){
  648.   const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(deviceID);
  649.   if(deviceInfo == nullptr) throw "Device ID out of range";
  650.  
  651.  
  652.   AudioDeviceInfo adeviceInfo;
  653.  
  654.   adeviceInfo.name                = deviceInfo->name;
  655.  
  656.   adeviceInfo.maxChannels.input   = deviceInfo->maxInputChannels;
  657.   adeviceInfo.maxChannels.output  = deviceInfo->maxOutputChannels;
  658.  
  659.   adeviceInfo.defLoLatency.input  = deviceInfo->defaultLowInputLatency;
  660.   adeviceInfo.defLoLatency.output = deviceInfo->defaultLowOutputLatency;
  661.  
  662.   adeviceInfo.defHiLatency.input  = deviceInfo->defaultHighInputLatency;
  663.   adeviceInfo.defHiLatency.output = deviceInfo->defaultHighOutputLatency;
  664.  
  665.   adeviceInfo.defSampleRate       = deviceInfo->defaultSampleRate;
  666.  
  667.  
  668.   return adeviceInfo;
  669. }
  670.  
  671.  
  672.  
  673.  
  674. bool audio::areParamsSupported(const AudioStreamParams* params,
  675.                                const char** reason_p)
  676. {
  677.   if(params == nullptr) throw "params = nullptr";
  678.  
  679.   PaStreamParameters inParams,  *_inParams  = nullptr;
  680.   PaStreamParameters outParams, *_outParams = nullptr;
  681.  
  682.  
  683.   f64 inDefSmpRate = -1.0;
  684.   if(params->inputDeviceID > -1){
  685.     _inParams = &inParams;
  686.  
  687.     inParams.device           = params->inputDeviceID;
  688.     inParams.channelCount     = params->inputChannels;
  689.     inParams.sampleFormat     = ConvertToPaSampleFormat(params->inputFormat);
  690.     inParams.suggestedLatency = params->inputSuggestedLatency;
  691.  
  692.     const PaDeviceInfo* inDevInfo = Pa_GetDeviceInfo(inParams.device);
  693.     if(inDevInfo == nullptr)
  694.       throw "invalid input device ID";
  695.  
  696.     inDefSmpRate = inDevInfo->defaultSampleRate;
  697.  
  698.     if(inParams.channelCount < 0)
  699.       inParams.channelCount = MIN(2, inDevInfo->maxInputChannels);
  700.  
  701.     if(inParams.suggestedLatency < 0.0)
  702.       inParams.suggestedLatency = inDevInfo->defaultHighInputLatency;
  703.   }
  704.  
  705.  
  706.   f64 outDefSmpRate = -1.0;
  707.   if(params->outputDeviceID > -1){
  708.     _outParams = &outParams;
  709.  
  710.     outParams.device           = params->outputDeviceID;
  711.     outParams.channelCount     = params->outputChannels;
  712.     outParams.sampleFormat     = ConvertToPaSampleFormat(params->outputFormat);
  713.     outParams.suggestedLatency = params->outputSuggestedLatency;
  714.  
  715.     const PaDeviceInfo* outDevInfo = Pa_GetDeviceInfo(outParams.device);
  716.     if(outDevInfo == nullptr)
  717.       throw "invalid output device ID";
  718.  
  719.     outDefSmpRate = outDevInfo->defaultSampleRate;
  720.  
  721.     if(outParams.channelCount < 0)
  722.       outParams.channelCount = MIN(2, outDevInfo->maxOutputChannels);
  723.  
  724.     if(outParams.suggestedLatency < 0.0)
  725.       outParams.suggestedLatency = outDevInfo->defaultHighOutputLatency;
  726.   }
  727.  
  728.  
  729.   f64 sampleRate = params->sampleRate;
  730.  
  731.   if(sampleRate < 0.0){
  732.     if(inDefSmpRate != -1.0  &&  outDefSmpRate != -1.0){
  733.       if(inDefSmpRate != outDefSmpRate) //idk how this would happen, but just in case
  734.         throw "input and output's default sample rates are different";
  735.       sampleRate = inDefSmpRate;
  736.  
  737.     } else if(inDefSmpRate != -1.0){
  738.       sampleRate = inDefSmpRate;
  739.  
  740.     } else if(outDefSmpRate != -1.0){
  741.       sampleRate = outDefSmpRate;
  742.  
  743.     }
  744.   }
  745.  
  746.  
  747.   PaError err = Pa_IsFormatSupported(_inParams, _outParams, params->sampleRate);
  748.  
  749.   if(err!=paNoError && reason_p!=nullptr) *reason_p = Pa_GetErrorText(err);
  750.  
  751.   return err == paNoError;
  752. }
  753.  
  754.  
  755.  
  756.  
  757. }; /* namespace kit */
  758. /******************************************************************************/
  759. /******************************************************************************/
  760. //"kit_w32\src\kit_win32\kit_Bitmap.cpp":
  761. #include "kit_Bitmap_shared.hpp"
  762.  
  763. #define KIT_INVALID_BITMAP _kit_invalid_bitmap
  764.  
  765. #define KIT_IS_INVALID_BITMAP (!_valid && !_constructing)
  766.  
  767.  
  768. namespace kit {
  769.  
  770. static const char _kit_invalid_bitmap[] = "invalid bitmap";
  771.  
  772.  
  773.  
  774.  
  775. void Bitmap::_constructFromMemory(const color::ARGB* pixelData, u32 width, u32 height,
  776.                                   Window* blit_dst, bool directAccess)
  777. {
  778.   _type = KIT_CLASSTYPE_BITMAP;
  779.  
  780.   //validate parameters
  781.   if(!width ) throw "width = 0";
  782.   if(!height) throw "height = 0";
  783.  
  784.   if(blit_dst == nullptr)
  785.     throw "blit_dst = nullptr"; //(blit_d[e]st[ination])
  786.   if(!KIT_IS_CLASS_TYPE(blit_dst, KIT_CLASSTYPE_WINDOW))
  787.     throw "*blit_dst is not a Window";
  788.   if(!KIT_IS_CLASS_VALID(blit_dst))
  789.     throw "*blit_dst is invalid";
  790.  
  791.   _WindowOpaque* win_opq = (_WindowOpaque*)KIT_GET_CLASS_OPAQUE(blit_dst);
  792.  
  793.  
  794.   //allocate memory for opaque struct (aka the internal bitmap thingy)
  795.   _opq = (_BitmapOpaque*)memory::alloc(sizeof(_BitmapOpaque));
  796.   if(_opq == nullptr) throw "ran out of memory creating _opq";
  797.   memory::set(_opq, 0, sizeof(_BitmapOpaque));
  798.  
  799.  
  800.   //fill in that internal bitmap thingy
  801.   if(!PopulateBitmapOpaque(*_opq, pixelData, width, height,
  802.                            win_opq, directAccess))
  803.   {
  804.     memory::free(&_opq);
  805.     throw "failed to create internal bitmap";
  806.   }
  807.  
  808.  
  809.   //initialize mutex
  810.   InitializeCriticalSectionAndSpinCount(&_opq->lock, KIT_LOCK_SPINCOUNT);
  811.  
  812.  
  813.   //set pixels to that of pixelData, if != nullptr
  814.   setPixelData(pixelData, width, height);
  815.  
  816.  
  817.   _valid = true;
  818.   _constructing = false;
  819. }
  820.  
  821.  
  822.  
  823.  
  824. //loads from a file
  825. Bitmap::Bitmap(const char* filePath, Window* blit_dst, bool directAccess){
  826.   BinaryData fileData(filePath); //will throw on failure to read file
  827.  
  828.   shape::point bmpSize; //filled in with the bitmap's size by _parse<format>
  829.   color::ARGB* pixelData = nullptr; //set by _parse<format> (must be freed after use!)
  830.  
  831.   switch(fileData.getMagic32()){
  832.     case KIT_MAGIC_QOI: pixelData = _parseQOI(fileData, bmpSize); break;
  833.     default: throw "unknown image format";
  834.   }
  835.  
  836.  
  837.   const char* errorText = nullptr;
  838.   try { _constructFromMemory(pixelData, bmpSize.x, bmpSize.y, blit_dst, directAccess);
  839.   } catch(const char* _errorText){ errorText = _errorText; }
  840.  
  841.   memory::free(&pixelData); //free intermediate pixel array
  842.   if(errorText != nullptr) throw errorText;
  843. }
  844.  
  845.  
  846.  
  847. Bitmap::~Bitmap(){
  848.   if(!_valid) return;
  849.   _valid = false;
  850.  
  851.   if(_opq != nullptr){
  852.     DeleteCriticalSection(&_opq->lock);
  853.     DeleteObject(_opq->handle);
  854.     DeleteDC(_opq->devCtx);
  855.     memory::free(&_opq);
  856.   }
  857. }
  858.  
  859.  
  860.  
  861.  
  862. bool Bitmap::isDirectAccess(){
  863.   if(KIT_IS_INVALID_BITMAP) throw KIT_INVALID_BITMAP;
  864.   return _opq->directAccess;
  865. }
  866.  
  867.  
  868.  
  869. color::ARGB* Bitmap::getPixels(){
  870.   if(KIT_IS_INVALID_BITMAP) throw KIT_INVALID_BITMAP;
  871.   if(_opq->directAccess) return _opq->pixels;
  872.   else throw "bitmap does not support direct access";
  873. }
  874.  
  875.  
  876.  
  877. shape::point Bitmap::getSize(){
  878.   if(KIT_IS_INVALID_BITMAP) throw KIT_INVALID_BITMAP;
  879.   return _opq->size;
  880. }
  881.  
  882.  
  883.  
  884. void Bitmap::getPixelData(color::ARGB* pixelDataOut){
  885.   if(KIT_IS_INVALID_BITMAP) throw KIT_INVALID_BITMAP;
  886.   if(pixelDataOut == nullptr) throw "pixelDataOut = nullptr";
  887.  
  888.   if(_opq->directAccess){
  889.     memory::copy(pixelDataOut, _opq->pixels,
  890.                  sizeof(color::ARGB)*_opq->size.x*_opq->size.y);
  891.  
  892.   } else {
  893.     GetDIBits(_opq->devCtx, _opq->handle, 0, _opq->size.y, pixelDataOut,
  894.               &_opq->info, DIB_RGB_COLORS);
  895.  
  896.   }
  897. }
  898.  
  899.  
  900.  
  901.  
  902. void Bitmap::setPixelData(const color::ARGB* pixelData, u32 width, u32 height){
  903.   if(KIT_IS_INVALID_BITMAP) throw KIT_INVALID_BITMAP;
  904.  
  905.   lock(true);
  906.  
  907.   //recreate or resize the bitmap if necessary
  908.   if(_opq->size.x!=width || _opq->size.y!=height){
  909.     if(!width ) width  = _opq->size.x;
  910.     if(!height) height = _opq->size.y;
  911.     if(!ResizeBitmapOpaque(*_opq, width, height)){
  912.       lock(false);
  913.       throw "failed to resize bitmap";
  914.     }
  915.  
  916.   }
  917.  
  918.  
  919.   //actually set the pixel data (but only if pixelData != nullptr)
  920.   if(pixelData != nullptr){
  921.     if(_opq->directAccess){
  922.       if(_opq->pixels != nullptr)
  923.         memory::copy(_opq->pixels, pixelData, sizeof(color::ARGB)*width*height);
  924.  
  925.     } else {
  926.       if(_opq->handle != nullptr)
  927.         SetDIBits(_opq->devCtx, _opq->handle, 0, height, pixelData,
  928.                   &_opq->info, DIB_RGB_COLORS);
  929.  
  930.     }
  931.   }
  932.  
  933.   lock(false);
  934. }
  935.  
  936.  
  937.  
  938. void Bitmap::setBlitDestination(Window* blit_dst){
  939.   if(KIT_IS_INVALID_BITMAP) throw KIT_INVALID_BITMAP;
  940.  
  941.   color::ARGB* pixelData = nullptr;
  942.  
  943.   //setPixelData also locks, but it's safe to lock >1 on same thread
  944.   lock(true);
  945.  
  946.   try {
  947.  
  948.     //store pixel data temporarily
  949.     size_t numPixels = _opq->size.x * _opq->size.y;
  950.     pixelData = (color::ARGB*)memory::alloc(sizeof(color::ARGB) * numPixels);
  951.     if(pixelData == nullptr) throw "failed to allocate pixel data cache";
  952.     getPixelData(pixelData); //fill pixelData with the bitmap's original pixel data
  953.  
  954.     //switch old window opaque with the new one
  955.     _opq->window = (_WindowOpaque*)KIT_GET_CLASS_OPAQUE(blit_dst);
  956.  
  957.     //recreate bitmap, before writing its pixel data back
  958.     setPixelData(pixelData, 0, 0);
  959.  
  960.     memory::free(&pixelData);
  961.     lock(false);
  962.  
  963.   } catch(const char* errorText){
  964.     //it's actually safe to pass nullptr (&pixelData or pixelData) to free,
  965.      //but i'll keep the if statement here for clarity
  966.     if(pixelData != nullptr) memory::free(&pixelData);
  967.     lock(false);
  968.     throw errorText;
  969.  
  970.   }
  971. }
  972.  
  973.  
  974.  
  975.  
  976. void Bitmap::lock(bool locked){
  977.   if(KIT_IS_INVALID_BITMAP) throw KIT_INVALID_BITMAP;
  978.   if(locked) EnterCriticalSection(&_opq->lock);
  979.   else       LeaveCriticalSection(&_opq->lock);
  980. }
  981.  
  982.  
  983.  
  984.  
  985. void Bitmap::blitRect(shape::rect* dst, shape::rect* src,
  986.                       color::ARGB transparency)
  987. {
  988.   if(KIT_IS_INVALID_BITMAP) throw KIT_INVALID_BITMAP;
  989.  
  990.   //if src = nullptr, blit the entire bitmap
  991.   shape::rect _src;
  992.   if(src != nullptr){
  993.     _src = *src;
  994.   } else {
  995.     _src.w = _opq->size.x;
  996.     _src.h = _opq->size.y;
  997.   }
  998.  
  999.   shape::point canvasSize = _opq->window->canvas.size;
  1000.  
  1001.   //if dst = nullptr, stretch the bitmap across the entire canvas
  1002.   shape::rect _dst;
  1003.   if(dst != nullptr){
  1004.     _dst = *dst;
  1005.     //also, if dst dimensions < 0, use source dimensions
  1006.     if(_dst.w < 0) _dst.w = _src.w;
  1007.     if(_dst.h < 0) _dst.h = _src.h;
  1008.   } else {
  1009.     _dst.w = canvasSize.x;
  1010.     _dst.h = canvasSize.y;
  1011.   }
  1012.  
  1013.  
  1014.   //don't blit if the bitmap would appear off-screen
  1015.   if(_dst.x<=-_dst.w      || _dst.y<=-_dst.h  ||
  1016.      _dst.x>=canvasSize.x || _dst.y>=canvasSize.y) return;
  1017.  
  1018.  
  1019.   lock(true);
  1020.  
  1021.   if(transparency.v == 0x80000000){ //use StretchBlt
  1022.     StretchBlt(_opq->window->canvas.devCtx, _dst.x, _dst.y, _dst.w, _dst.h,
  1023.                               _opq->devCtx, _src.x, _src.y, _src.w, _src.h, SRCCOPY);
  1024.  
  1025.   } else { //use TransparentBlt
  1026.     transparency.v &= 0x00ffffff; //set high byte of transparent color to 0 just in case
  1027.     TransparentBlt(_opq->window->canvas.devCtx, _dst.x, _dst.y, _dst.w, _dst.h,
  1028.                                   _opq->devCtx, _src.x, _src.y, _src.w, _src.h, transparency.v);
  1029.  
  1030.   }
  1031.  
  1032.   lock(false);
  1033. }
  1034.  
  1035.  
  1036.  
  1037. void Bitmap::blit(s32 x, s32 y, f32 scale,
  1038.                   color::ARGB transparency)
  1039. {
  1040.   shape::rect dst;
  1041.   dst.x = x;
  1042.   dst.y = y;
  1043.   dst.w = (s32)( (f32)_opq->size.x*scale + 0.5f ); //+0.5 for rounding to
  1044.   dst.h = (s32)( (f32)_opq->size.y*scale + 0.5f );  //the nearest pixel
  1045.  
  1046.   //by making the src parameter nullptr, the entire bitmap is copied
  1047.   blitRect(&dst, nullptr, transparency);
  1048. }
  1049.  
  1050.  
  1051.  
  1052. void Bitmap::blitCentered(s32 xCenter, s32 yCenter, f32 scale,
  1053.                           color::ARGB transparency)
  1054. {
  1055.   shape::rect dst;
  1056.   dst.w = (s32)( (f32)_opq->size.x*scale + 0.5f ); //+0.5 for rounding to
  1057.   dst.h = (s32)( (f32)_opq->size.y*scale + 0.5f );  //the nearest pixel
  1058.   dst.x = xCenter - dst.w/2;
  1059.   dst.y = yCenter - dst.h/2;
  1060.  
  1061.   //by making the src parameter nullptr, the entire bitmap is copied
  1062.   blitRect(&dst, nullptr, transparency);
  1063. }
  1064.  
  1065.  
  1066.  
  1067.  
  1068. }; /* namespace kit */
  1069.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement