//############################################################################
//
// LaserBoy !!!
//
// by James Lehman
// Extra Stimulus Inc.
// james@akrobiz.com
//
// began: October 2003
//
// Copyright 2003 to 2023 James Lehman.
// This source is distributed under the terms of the GNU General Public License.
//
// LaserBoy_wave.cpp is part of LaserBoy.
//
// LaserBoy is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// LaserBoy is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with LaserBoy. If not, see .
//
//############################################################################
/*
#include
int main(int argc, char **argv) {
SDL_Init(SDL_INIT_AUDIO);
SDL_AudioSpec wavSpec;
Uint32 wavLength;
Uint8 *wavBuffer;
SDL_LoadWAV("speaker-test.wav", &wavSpec, &wavBuffer, &wavLength);
SDL_AudioDeviceID deviceID = SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, 0);
SDL_QueueAudio(deviceID, wavBuffer, wavLength);
SDL_PauseAudioDevice(deviceID, 0);
SDL_Delay(30000);
SDL_CloseAudioDevice(deviceID);
SDL_FreeWAV(wavBuffer);
SDL_Quit();
return 0;
}
typedef struct circularBufferStruct
{
short *buffer;
int cells;
short *readPoint;
short *writePoint;
} circularBuffer;
// This method is called at initialization:
int initialize_audio(int channels)
{
channel = channels;
// Check if sound is disabled
if (sampleRate != 0)
{
// Initialize SDL Audio
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
{
SDL_Log("SDL fails to initialize audio subsystem!\n%s", SDL_GetError());
return 1;
}
// Number of samples per frame
samplesPerFrame = (double)sampleRate / (double)framesPerSecond * channel;
audioSamplesSize = samplesPerFrame * bytesPerSample; // Bytes
audioBufferSize = audioSamplesSize * 10; // Bytes
// Set and clear circular buffer
audioBuffer.buffer = malloc(audioBufferSize); // Bytes, must be a multiple of audioSamplesSize
memset(audioBuffer.buffer, 0, audioBufferSize);
audioBuffer.cells = (audioBufferSize) / sizeof(short); // Cells, not Bytes!
audioBuffer.readPoint = audioBuffer.buffer;
audioBuffer.writePoint = audioBuffer.readPoint + (short)samplesPerFrame;
}
else
samplesPerFrame = 0;
// First frame
return samplesPerFrame;
}
// This is the SDL method callback from want.callback:
void audioCallback(void *userdata, uint8_t *stream, int len)
{
SDL_memset(stream, 0, len);
if (audioSamplesSize == 0)
return;
if (len > audioSamplesSize)
{
len = audioSamplesSize;
}
SDL_MixAudioFormat(stream, (const Uint8 *)audioBuffer.readPoint, AUDIO_S16SYS, len, SDL_MIX_MAXVOLUME);
audioBuffer.readPoint += (short)samplesPerFrame;
if (audioBuffer.readPoint >= audioBuffer.buffer + audioBuffer.cells)
audioBuffer.readPoint = audioBuffer.readPoint - audioBuffer.cells;
}
This method is called at each frame (after first pass we require only the amount of samples):
int update_audio(short *buffer)
{
// Check if sound is disabled
if (sampleRate != 0)
{
memcpy(audioBuffer.writePoint, buffer, audioSamplesSize); // Bytes
audioBuffer.writePoint += (short)samplesPerFrame; // Cells
if (audioBuffer.writePoint >= audioBuffer.buffer + audioBuffer.cells)
audioBuffer.writePoint = audioBuffer.writePoint - audioBuffer.cells;
if (firstTime)
{
// Set required audio specs
want.freq = sampleRate;
want.format = AUDIO_S16SYS;
want.channels = channel;
want.samples = samplesPerFrame / channel; // total samples divided by channel count
want.padding = 0;
want.callback = audioCallback;
want.userdata = NULL;
device = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(0, 0), 0, &want, &have, 0);
SDL_PauseAudioDevice(device, 0);
firstTime = 0;
}
}
else
samplesPerFrame = 0;
// Next frame
return samplesPerFrame;
}
* Copyright (c) 2018, 2019 Amine Ben Hassouna
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any
* person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the
* Software without restriction, including without
* limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software
* is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice
* shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
#include
#include
#include
// Define MAX and MIN macros
#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
// Define screen dimensions
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
#define WAVES_SOUND "assets/waves-at-baltic-sea-shore/waves-at-baltic-sea-shore.wav"
int main(int argc, char* argv[])
{
// Unused argc, argv
(void) argc;
(void) argv;
// Initialize SDL
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
{
printf("SDL could not be initialized!\n"
"SDL_Error: %s\n", SDL_GetError());
return 0;
}
#if defined linux && SDL_VERSION_ATLEAST(2, 0, 8)
// Disable compositor bypass
if(!SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"))
{
printf("SDL can not disable compositor bypass!\n");
return 0;
}
#endif
// Create window
SDL_Window *window = SDL_CreateWindow("SDL2 audio sample (Press SPACE to pause/play)",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
if(!window)
{
printf("Window could not be created!\n"
"SDL_Error: %s\n", SDL_GetError());
}
else
{
// Create renderer
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if(!renderer)
{
printf("Renderer could not be created!\n"
"SDL_Error: %s\n", SDL_GetError());
}
else
{
// Load .WAV sound
SDL_AudioSpec wavSpec;
Uint32 wavLength;
Uint8 *wavBuffer;
if(!SDL_LoadWAV(WAVES_SOUND, &wavSpec, &wavBuffer, &wavLength))
{
printf(".WAV sound '%s' could not be loaded!\n"
"SDL_Error: %s\n", WAVES_SOUND, SDL_GetError());
return 0;
}
// Open audio device
SDL_AudioDeviceID deviceId = SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, 0);
if(!deviceId)
{
printf("Audio device could not be opened!\n"
"SDL_Error: %s\n", SDL_GetError());
SDL_FreeWAV(wavBuffer);
return 0;
}
// Queue audio (~ Add to playlist)
if(SDL_QueueAudio(deviceId, wavBuffer, wavLength) < 0)
{
printf("Audio could not be queued!\n"
"SDL_Error: %s\n", SDL_GetError());
SDL_CloseAudioDevice(deviceId);
SDL_FreeWAV(wavBuffer);
return 0;
}
// Play audio
SDL_PauseAudioDevice(deviceId, 0);
// Declare rect of square
SDL_Rect squareRect;
// Square dimensions: Half of the min(SCREEN_WIDTH, SCREEN_HEIGHT)
squareRect.w = MIN(SCREEN_WIDTH, SCREEN_HEIGHT) / 2;
squareRect.h = MIN(SCREEN_WIDTH, SCREEN_HEIGHT) / 2;
// Square position: In the middle of the screen
squareRect.x = SCREEN_WIDTH / 2 - squareRect.w / 2;
squareRect.y = SCREEN_HEIGHT / 2 - squareRect.h / 2;
// Declare rects of pause symbol
SDL_Rect pauseRect1, pauseRect2;
pauseRect1.h = squareRect.h / 2;
pauseRect1.w = 40;
pauseRect1.x = squareRect.x + (squareRect.w - pauseRect1.w*3) / 2;
pauseRect1.y = squareRect.y + squareRect.h / 4;
pauseRect2 = pauseRect1;
pauseRect2.x += pauseRect1.w * 2;
// Event loop exit flag
bool quit = false;
// Event loop
while(!quit)
{
SDL_Event e;
// Wait indefinitely for the next available event
SDL_WaitEvent(&e);
// User requests quit
if(e.type == SDL_QUIT)
{
quit = true;
}
else if(e.type == SDL_KEYDOWN)
{
switch (e.key.keysym.sym)
{
case SDLK_SPACE:
if(SDL_GetAudioDeviceStatus(deviceId) == SDL_AUDIO_PLAYING)
SDL_PauseAudioDevice(deviceId, 1);
else if(SDL_GetAudioDeviceStatus(deviceId) == SDL_AUDIO_PAUSED)
SDL_PauseAudioDevice(deviceId, 0);
break;
}
}
// Initialize renderer color white for the background
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
// Clear screen
SDL_RenderClear(renderer);
// Set renderer color blue to draw the square
SDL_SetRenderDrawColor(renderer, 0x19, 0x71, 0xA9, 0xFF);
// Draw filled square
SDL_RenderFillRect(renderer, &squareRect);
// Check pause status
if(SDL_GetAudioDeviceStatus(deviceId) == SDL_AUDIO_PAUSED)
{
// Set renderer color white to draw the pause symbol
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
// Draw pause symbol
SDL_RenderFillRect(renderer, &pauseRect1);
SDL_RenderFillRect(renderer, &pauseRect2);
}
// Update screen
SDL_RenderPresent(renderer);
}
// Clean up audio
SDL_CloseAudioDevice(deviceId);
SDL_FreeWAV(wavBuffer);
// Destroy renderer
SDL_DestroyRenderer(renderer);
}
// Destroy window
SDL_DestroyWindow(window);
}
// Quit SDL
SDL_Quit();
return 0;
}
*/