int osd_update_audio_stream(INT16 *buffer) { // Soundcard switch off? if (Machine->sample_rate == 0) return samples_per_frame; Uint32 unBytesQueued = SDL_GetQueuedAudioSize(audio_device); if (unBytesQueued == 0) { ++fifo_underrun; // Queue some silence to start buffering uint8_t silence[bytes_per_frame]; memset(silence, 0, sizeof(silence)); SDL_QueueAudio(audio_device, silence, sizeof(silence)); } if (unBytesQueued > 10*bytes_per_frame) { ++fifo_overrun; SDL_ClearQueuedAudio(audio_device); } profiler_mark(PROFILER_USER1); if (attenuation < 0) { /* FIXME: Need to attenuate the audio stream? */ } SDL_QueueAudio(audio_device, buffer, bytes_per_frame); profiler_mark(PROFILER_END); return samples_per_frame; }
void SoundSystemImpl::queueAudio() { #ifdef IMGUI_ENABLE const int max_samples = mAudioSpecObtained.samples * mAudioSpecObtained.channels; const uint32_t bytePerSample = sizeof(float); SDL_AudioDeviceID audioDeviceID = mAudioDeviceId; uint32_t alreadyQueuedByte = SDL_GetQueuedAudioSize(audioDeviceID); int16_t alreadyQueued = numeric_cast<int16_t>(alreadyQueuedByte / bytePerSample); int16_t toQueue = max_samples - alreadyQueued; while (g_debug_sample_buffer.max_size() <= g_debug_sample_buffer.size()) { g_debug_sample_buffer.read(); } g_debug_sample_buffer.write(mFrameMixer.size()); while (g_debug_required_buffer.max_size() <= g_debug_required_buffer.size()) { g_debug_required_buffer.read(); } g_debug_required_buffer.write(toQueue); #endif int audioError = SDL_QueueAudio(audioDeviceID, (const void*)mFrameMixer.data(), mFrameMixer.size() * bytePerSample); if (0 != audioError) { printf("Audio queue error %s\n", SDL_GetError()); } mFrameMixer.clear(); }
int SNDDMA_AvailableCaptureSamples(void) { #ifdef USE_SDL_AUDIO_CAPTURE // divided by 2 to convert from bytes to (mono16) samples. return sdlCaptureDevice ? (SDL_GetQueuedAudioSize(sdlCaptureDevice) / 2) : 0; #else return 0; #endif }
int16_t SoundSystemImpl::samplesNeeded() const { const int freq = mAudioSpecObtained.freq; const int max_samples = mAudioSpecObtained.samples * mAudioSpecObtained.channels; const uint32_t bytePerSample = sizeof(float); const uint32_t alreadyQueuedByte = SDL_GetQueuedAudioSize(mAudioDeviceId); const int16_t alreadyQueued = numeric_cast<int16_t>(alreadyQueuedByte / bytePerSample); const int16_t toQueue = max_samples - alreadyQueued; return toQueue; }
static unsigned int S_CaptureDriverUpdate (void* driverContext, unsigned char* buffer, int minBytes, int maxBytes) { SDL_AudioDeviceID inputdevid = (SDL_AudioDeviceID)driverContext; unsigned int available = SDL_GetQueuedAudioSize (inputdevid); if (available > minBytes) { return SDL_DequeueAudio (inputdevid, buffer, maxBytes); } return 0; }
void audio_play() { if (paused) { updateok = true; return; } bufsize = 2 * channels * (conf.audio_sample_rate / framerate); if (conf.audio_api == 0) { // SDL #if SDL_VERSION_ATLEAST(2,0,4) SDL_QueueAudio(dev, (const void*)audiobuf, bufsize); // Clear the audio queue arbitrarily to avoid it backing up too far if (SDL_GetQueuedAudioSize(dev) > (Uint32)(bufsize * 3)) { SDL_ClearQueuedAudio(dev); } #endif } #ifndef _MINGW else if (conf.audio_api == 1) { // libao ao_play(aodevice, (char*)audiobuf, bufsize); } #endif updateok = true; }
bool timing_frameskip() { // Calculate whether to skip a frame or not if (conf.audio_api == 0) { // SDL // Wait until the audio is drained #if SDL_VERSION_ATLEAST(2,0,4) while (SDL_GetQueuedAudioSize(dev) > (Uint32)bufsize) { if (conf.timing_limiter) { SDL_Delay(1); } } #endif } static int flipper = 1; if (altspeed) { if (flipper > 2) { flipper = 0; return false; } else { flipper++; return true; } } return false; }
void loop() { #ifdef __EMSCRIPTEN__ if (done || (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING)) { emscripten_cancel_main_loop(); } else #endif { /* The device from SDL_OpenAudio() is always device #1. */ const Uint32 queued = SDL_GetQueuedAudioSize(1); SDL_Log("Device has %u bytes queued.\n", (unsigned int) queued); if (queued <= 8192) { /* time to requeue the whole thing? */ if (SDL_QueueAudio(1, wave.sound, wave.soundlen) == 0) { SDL_Log("Device queued %u more bytes.\n", (unsigned int) wave.soundlen); } else { SDL_Log("Device FAILED to queue %u more bytes: %s\n", (unsigned int) wave.soundlen, SDL_GetError()); } } } }
int main(int argc, char *argv[]) { int i; char filename[4096]; /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); /* Load the SDL library */ if (SDL_Init(SDL_INIT_AUDIO) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); return (1); } if (argc > 1) { SDL_strlcpy(filename, argv[1], sizeof(filename)); } else { SDL_strlcpy(filename, "sample.wav", sizeof(filename)); } /* Load the wave file into memory */ if (SDL_LoadWAV(filename, &wave.spec, &wave.sound, &wave.soundlen) == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError()); quit(1); } wave.spec.callback = NULL; /* we'll push audio. */ #if HAVE_SIGNAL_H /* Set the signals */ #ifdef SIGHUP signal(SIGHUP, poked); #endif signal(SIGINT, poked); #ifdef SIGQUIT signal(SIGQUIT, poked); #endif signal(SIGTERM, poked); #endif /* HAVE_SIGNAL_H */ /* Initialize fillerup() variables */ if (SDL_OpenAudio(&wave.spec, NULL) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open audio: %s\n", SDL_GetError()); SDL_FreeWAV(wave.sound); quit(2); } /*static x[99999]; SDL_QueueAudio(1, x, sizeof (x));*/ /* Let the audio run */ SDL_PauseAudio(0); /* Note that we stuff the entire audio buffer into the queue in one shot. Most apps would want to feed it a little at a time, as it plays, but we're going for simplicity here. */ while (!done && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING)) { /* The device from SDL_OpenAudio() is always device #1. */ const Uint32 queued = SDL_GetQueuedAudioSize(1); SDL_Log("Device has %u bytes queued.\n", (unsigned int) queued); if (queued <= 8192) { /* time to requeue the whole thing? */ if (SDL_QueueAudio(1, wave.sound, wave.soundlen) == 0) { SDL_Log("Device queued %u more bytes.\n", (unsigned int) wave.soundlen); } else { SDL_Log("Device FAILED to queue %u more bytes: %s\n", (unsigned int) wave.soundlen, SDL_GetError()); } } SDL_Delay(100); /* let it play for awhile. */ } /* Clean up on signal */ SDL_CloseAudio(); SDL_FreeWAV(wave.sound); SDL_Quit(); return 0; }
//******************************************************* MAIN ******************************* int main(int argc, char* argv[]){ //set up sdl SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); SDL_Window *Window = SDL_CreateWindow("Handmade Hero", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_RESIZABLE); if(Window){ SDL_Renderer *Renderer = SDL_CreateRenderer(Window, -1, 0); if(Renderer){ // VIDEO sdl_offscreen_buffer Buffer = {}; // if non-initialized, declaring variables in a loop fails on SDLResizeTexture with a pointer error - im blaming the compiler sdl_window_dimension Dimension = SDLGetWindowDimension(Window); SDLResizeTexture(&Buffer, Renderer, Dimension.Width, Dimension.Height); keystates Keys = {}; //AUDIO sdl_sound_output sound_output = sdl_sound_outputH(48000); //open audio SDLInitAudio(sound_output.SamplesPerSecond, sound_output.SamplesPerSecond * sound_output.BytesPerSample / 60); SDL_PauseAudio(0); //BW: state area allocation void *new_state_area = malloc(128*1024*1024);//need ~2 MB at least; give it 128 MiB -- 2MB for video; dont know audio void *prev_state_area = malloc(1024);// should be sizeof(state0), or sizeof(biggest statetype) later //apparently we didnt have enough memory, but only crashed sometimes? this fixed it void *state; { uint8 *next_ptr = (uint8*)prev_state_area; anim_comp *animation = (anim_comp*)next_ptr; next_ptr += sizeof(anim_comp); init_anim_comp(animation, 0,0); state0 *stateptr = (state0*)next_ptr; printf("state0 size %ld\n", sizeof(state0)); uint64 stateptrn = (uint64)stateptr; uint64 sizeptr = (uint64)&(stateptr->size); uint64 deepc_ptr = (uint64)&(stateptr->deep_count); uint64 anim_ptr = (uint64)&(stateptr->animation); uint64 tsine_ptr = (uint64)&(stateptr->tSine); uint64 tvol_ptr = (uint64)&(stateptr->ToneVolume); uint64 thz_ptr = (uint64)&(stateptr->ToneHz); uint64 pu_ptr = (uint64)&(stateptr->pitch_up_was_pressed); printf("offset begin %lu\n", sizeptr - stateptrn); printf("width of size %lu\n", deepc_ptr - sizeptr); printf("width of deepc %lu\n", anim_ptr - deepc_ptr); printf("width of animpt %lu\n", tsine_ptr - anim_ptr); printf("width of tsine %lu\n", tvol_ptr - tsine_ptr); printf("width of tvol %lu\n", thz_ptr - tvol_ptr); printf("width of thz %lu\n", pu_ptr - thz_ptr); next_ptr += sizeof(state0); init_state0(stateptr, animation, 3000, 256, 0); state = stateptr; //return 0; } uint64 LastCounter = SDL_GetPerformanceCounter(); uint64 LastCycleCount = _rdtsc(); uint64 PerfCountFrequency = SDL_GetPerformanceFrequency(); bool running = true; //main loop printf("enter main event loop\n"); while(running){ ///////NP_UPDATE///////////// //event capturing event_return events = eventHandler(&Keys); if(events.shouldQuit) running = false; //setup for p state_window_info Wi = {}; Wi.Height = Buffer.Height; Wi.Width = Buffer.Width; Wi.Pitch = Buffer.Pitch; int TargetQueueBytes = sound_output.LatencySampleCount * sound_output.BytesPerSample; state_sound_info Si = {}; Si.BytesToGet = TargetQueueBytes - SDL_GetQueuedAudioSize(1); Si.BytesPerSample = sound_output.BytesPerSample; Si.SamplesPerSecond = sound_output.SamplesPerSecond; uint64 state_size = 0; uint64 vbuffer_size = Buffer.Height * Buffer.Pitch; uint64 abuffer_size = Si.BytesToGet; state_return next; { //in case(statetype) or similar next = P_update_state0(*(state0*)state, new_state_area, Keys, Wi, Si); //p should return state_size? and also, what statetype we are in -> later state_size = sizeof(state0); } //GARBAGE COLLECTOR //move this state to previous state //fmemcpy(prev_state_area, new_state_area, state_size); //shallow copy, as supposed //printf("hi\n"); deepcopy(prev_state_area, next.state, new_state_area, (uint8*)new_state_area + 128*1024*1024); //TODO(md): DEEPCPY //queue audio if (Si.BytesToGet > 0) SDL_QueueAudio(1, next.abuffer, abuffer_size); //render SDLUpdateWindow(Window, Renderer, Buffer, next.vbuffer); uint64 EndCycleCount = _rdtsc(); uint64 EndCounter = SDL_GetPerformanceCounter(); uint64 CounterElapsed = EndCounter - LastCounter; uint64 CyclesElapsed = EndCycleCount - LastCycleCount; real64 MSPerFrame = (((1000.0f * (real64)CounterElapsed) / (real64)PerfCountFrequency)); real64 FPS = (real64)PerfCountFrequency / (real64)CounterElapsed; real64 MCPF = ((real64)CyclesElapsed / (1000.0f * 1000.0f)); printf("%.02fms/f, %.02f/s, %.02fmc/f\n", MSPerFrame, FPS, MCPF); LastCycleCount = EndCycleCount; LastCounter = EndCounter; } } } //if(Renderer, Window) SDL_Quit(); return 0; }
void loop(NES nesSystem, const char * fileLoc) { if (!init_sdl(fileLoc)) { std::cerr << "SDL did not initialize, quitting" << std::endl; return; } Debugger debugger(&nesSystem); //game loop variables double frequency = SDL_GetPerformanceFrequency(); uintmax_t startTime = SDL_GetPerformanceCounter(); bool paused = true; SDL_Event event; for (int x = 0; x < 256 * 240; x++) localPixels[x] = 0; draw(nesSystem.m_nesCPU.m_nesPPU.m_pixels); //draw screen black SDL_PauseAudioDevice(sdlAudioDevice, 0); //unpause audio for (;;) { //1 process events if (!process_events(&event, &nesSystem.m_nesCPU.m_controllerByte, &paused)) { break; } //2 logic if (!paused) { do { enum DebuggerEventStatus debugEventStatus = debugger.pre_instr_events(); if (debugEventStatus == BREAK_HIT || debugEventStatus == CRASH_IMMINENT) { paused = true; break; } else if (debugEventStatus == DONE_LOGGED_EXECUTION) { paused = true; } //execute one cpu opcode nesSystem.m_nesCPU.execute_next_opcode(); debugger.post_instr_events(); //ppu catches up nesSystem.m_nesCPU.m_nesPPU.tick(&nesSystem.m_nesCPU.m_NMI, &nesSystem.m_nesCPU.m_cpuClock); } while (!nesSystem.m_nesCPU.m_nesPPU.m_draw && !paused); //3.1 audio nesSystem.m_nesCPU.m_nesAPU.fill_buffer(&nesSystem, &nesSystem.m_nesCPU.m_IRQ); if (SDL_GetQueuedAudioSize(sdlAudioDevice) > (unsigned int) nesSystem.m_nesCPU.m_nesAPU.m_audioBufferSize * 10) { //prevents audio from becoming too out of sync SDL_ClearQueuedAudio(sdlAudioDevice); } SDL_QueueAudio(sdlAudioDevice, (void *) nesSystem.m_nesCPU.m_nesAPU.m_audioBuffer, nesSystem.m_nesCPU.m_nesAPU.m_audioBufferSize); } else { enum DebuggerCommandStatus commandStatus; do { commandStatus = debugger.cmd(); } while (commandStatus == CONTINUE_DEBUG); //SDL_FlushEvents(SDL_USEREVENT, SDL_LASTEVENT); if (commandStatus == RUN_NO_FOCUS) { paused = false; } else if (commandStatus == QUIT) { break; } else if (commandStatus == RUN_RETURN_FOCUS) { paused = false; SDL_RaiseWindow(window); } else { break; } } //3.2 video draw(nesSystem.m_nesCPU.m_nesPPU.m_pixels); //4 sync framerate double delay = MILLISECONDS_PER_FRAME - (((SDL_GetPerformanceCounter() - startTime) / frequency) * 1000) - 0.5; if (delay > 0) { std::this_thread::sleep_for(std::chrono::microseconds((int) (delay * 1000))); } while ((((SDL_GetPerformanceCounter() - startTime) / frequency) * 1000) < MILLISECONDS_PER_FRAME) { } startTime = SDL_GetPerformanceCounter(); } SDL_PauseAudioDevice(sdlAudioDevice, 1); //pause SDL_ClearQueuedAudio(sdlAudioDevice); //clear audio queue close_sdl(); return; }