diff --git a/examples/audio/mixed_processor/coin.wav b/examples/audio/mixed_processor/coin.wav new file mode 100644 index 0000000..ad95bfb Binary files /dev/null and b/examples/audio/mixed_processor/coin.wav differ diff --git a/examples/audio/mixed_processor/country.mp3 b/examples/audio/mixed_processor/country.mp3 new file mode 100644 index 0000000..91066cc Binary files /dev/null and b/examples/audio/mixed_processor/country.mp3 differ diff --git a/examples/audio/mixed_processor/main.go b/examples/audio/mixed_processor/main.go new file mode 100644 index 0000000..d9d8835 --- /dev/null +++ b/examples/audio/mixed_processor/main.go @@ -0,0 +1,155 @@ +/******************************************************************************************* +* +* raylib [audio] example - Mixed audio processing +* +* Example originally created with raylib 4.2, last time updated with raylib 4.2 +* +* Example contributed by hkc (@hatkidchan) and reviewed by Ramon Santamaria (@raysan5) +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2023 hkc (@hatkidchan) +* +********************************************************************************************/ +package main + +import ( + "fmt" + "math" + + rl "github.com/gen2brain/raylib-go/raylib" +) + +const ( + screenWidth = 800 + screenHeight = 450 +) + +var exponent float32 = 1.0 // Audio exponentiation value +var averageVolume [400]float32 // Average volume history + +func main() { + rl.InitWindow(screenWidth, screenHeight, "raylib [audio] example - processing mixed output") + + rl.InitAudioDevice() // Initialize audio device + rl.AttachAudioMixedProcessor(ProcessAudio) + + music := rl.LoadMusicStream("country.mp3") + sound := rl.LoadSound("coin.wav") + + rl.PlayMusicStream(music) + + rl.SetTargetFPS(60) // Set our game to run at 60 frames-per-second + + // Main game loop + for !rl.WindowShouldClose() { // Detect window close button or ESC key + rl.UpdateMusicStream(music) // Update music buffer with new stream data + + // Modify processing variables + if rl.IsKeyPressed(rl.KeyLeft) { + exponent -= 0.05 + } + if rl.IsKeyPressed(rl.KeyRight) { + exponent += 0.05 + } + if rl.IsKeyPressed(rl.KeyDown) { + exponent -= 0.25 + } + if rl.IsKeyPressed(rl.KeyUp) { + exponent += 0.25 + } + + // Make sure that exponent stays between 0.5 and 3 + exponent = clamp(exponent, 0.5, 3) + + if rl.IsKeyPressed(rl.KeySpace) { + rl.PlaySound(sound) + } + + // Draw + rl.BeginDrawing() + + rl.ClearBackground(rl.RayWhite) + + rl.DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, rl.LightGray) + + rl.DrawText(fmt.Sprintf("EXPONENT = %.2f", exponent), 215, 180, 20, rl.LightGray) + + rl.DrawRectangle(199, 199, 402, 34, rl.LightGray) + for i := int32(0); i < 400; i++ { + rl.DrawLine(201+i, 232-int32(averageVolume[i]*32), 201+i, 232, rl.Maroon) + } + rl.DrawRectangleLines(199, 199, 402, 34, rl.Gray) + + rl.DrawText("PRESS SPACE TO PLAY OTHER SOUND", 200, 250, 20, rl.LightGray) + rl.DrawText("USE LEFT AND RIGHT ARROWS TO ALTER DISTORTION", 140, 280, 20, rl.LightGray) + + rl.EndDrawing() + } + + // De-Initialization + rl.UnloadMusicStream(music) // Unload music stream buffers from RAM + rl.DetachAudioMixedProcessor(ProcessAudio) // Disconnect audio processor + rl.CloseAudioDevice() // Close audio device (music streaming is automatically stopped) + + rl.CloseWindow() // Close window and OpenGL context +} + +// ProcessAudio is the audio processing function +func ProcessAudio(buffer []float32, frames int) { + var average float32 // Temporary average volume + maxFrame := frames / 2 + + // Each frame has 2 samples (left and right), + // so we should loop `frames / 2` times + for frame := 0; frame < maxFrame; frame++ { + left := &buffer[frame*2+0] // Left channel + right := &buffer[frame*2+1] // Right channel + + // Modify left and right channel samples with exponent + *left = pow(abs(*left), exponent) * sgn(*left) + *right = pow(abs(*right), exponent) * sgn(*right) + + // Accumulating average volume + average += abs(*left) / float32(maxFrame) + average += abs(*right) / float32(maxFrame) + } + + // Shift average volume history buffer to the left + for i := 0; i < 399; i++ { + averageVolume[i] = averageVolume[i+1] + } + + // Add the new average value + averageVolume[399] = average +} + +// Helper functions to make the code shorter +// (using less type conversions) +// (Golang: Please make the `math` package generic! This is ridiculous :-) +func abs(value float32) float32 { + return float32(math.Abs(float64(value))) +} + +func pow(value, exponent float32) float32 { + return float32(math.Pow(float64(value), float64(exponent))) +} + +func sgn(value float32) float32 { + if value < 0 { + return -1 + } else if value > 0 { + return 1 + } + return 0 +} +func clamp(value, min, max float32) float32 { + if value < min { + return min + } + if value > max { + return max + } + return value +} diff --git a/examples/audio/sound_multi/main.go b/examples/audio/sound_multi/main.go new file mode 100644 index 0000000..b91485c --- /dev/null +++ b/examples/audio/sound_multi/main.go @@ -0,0 +1,65 @@ +/******************************************************************************************* +* +* raylib [audio] example - Playing sound multiple times +* +* Example originally created with raylib 4.6 +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2023 Jeffery Myers (@JeffM2501) +* +********************************************************************************************/ +package main + +import rl "github.com/gen2brain/raylib-go/raylib" + +const ( + screenWidth = 800 + screenHeight = 450 + maxSounds = 10 +) + +var soundArray [maxSounds]rl.Sound +var currentSound int32 + +func main() { + rl.InitWindow(screenWidth, screenHeight, "raylib [audio] example - playing sound multiple times") + + // Initialize audio device + rl.InitAudioDevice() + + // Load WAV audio file into the first slot as the 'source' sound + // this sound owns the sample data + soundArray[0] = rl.LoadSound("sound.wav") + + for i := 1; i < maxSounds; i++ { + // Load an alias of the sound into slots 1-9. + // These do not own the sound data, but can be played + soundArray[i] = rl.LoadSoundAlias(soundArray[0]) + } + + rl.SetTargetFPS(60) // Set our game to run at 60 frames-per-second + + for !rl.WindowShouldClose() { // Detect window close button or ESC key + if rl.IsKeyPressed(rl.KeySpace) { + rl.PlaySound(soundArray[currentSound]) // play the next open sound slot + currentSound++ // increment the sound slot + if currentSound >= maxSounds { // if the sound slot is out of bounds, go back to 0 + currentSound = 0 + } + + // Note: a better way would be to look at the list for the first sound that is not playing and use that slot + } + + rl.BeginDrawing() + rl.ClearBackground(rl.RayWhite) + rl.DrawText("Press SPACE to PLAY a WAV sound!", 200, 180, 20, rl.LightGray) + rl.EndDrawing() + } + + rl.UnloadSound(soundArray[0]) // Unload source sound data + rl.CloseAudioDevice() // Close audio device + + rl.CloseWindow() // Close window and OpenGL context +} diff --git a/examples/audio/sound_multi/sound.wav b/examples/audio/sound_multi/sound.wav new file mode 100644 index 0000000..b5d01c9 Binary files /dev/null and b/examples/audio/sound_multi/sound.wav differ