Created
December 31, 2014 02:51
-
-
Save triplefox/62529b0463b852031121 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Generate and playback a sine tone | |
import sdl2 | |
import sdl2/audio | |
import math | |
# Audio settings: | |
const Channels = 1 | |
const RQSizeInSamples = 4096 * Channels | |
const BytesPerSample = 4 | |
let SampleRate = 44100 | |
# What tone to generate: | |
let Frequence = 440 # Hz | |
let Volume = 0.1 # [0..1] | |
# Current playback position | |
var x = 0 | |
# Generate a sine wave | |
let c = float(SampleRate) / float(Frequence) | |
proc SineAmplitude(): float32 = float32(sin(float(x) / c * 2 * PI) * Volume) | |
proc Envelope(): float32 = max(0.0, 1 - (x/44100)) | |
proc Synthesis(): float32 = SineAmplitude() * Envelope() | |
type | |
Array32Part{.unchecked.} = array[0..0, float32] | |
Buffer32 = ref object | |
samples: int | |
bytes: int | |
data: ptr Array32Part | |
proc AllocBuffer32(samples : int): Buffer32 = | |
let bytes = samples*(sizeof(float32)) | |
Buffer32(samples: samples, bytes : bytes, data: cast[ptr Array32Part](alloc0(bytes))) | |
proc DeallocBuffer32(b : Buffer32) = | |
dealloc(cast[pointer](b.data)) | |
var buffer:Buffer32 | |
proc AudioCallback_Direct(userdata: pointer; stream: ptr uint8; len: cint) {.cdecl.} = | |
for i in 0..buffer.samples - 1: | |
cast[ptr float32](cast[int](stream) + i * BytesPerSample)[] = Synthesis() | |
inc(x) | |
proc AudioCallback_OwnBuf(userdata: pointer; stream: ptr uint8; len: cint) {.cdecl.} = | |
for i in 0..buffer.samples - 1: | |
buffer.data[i] = Synthesis() | |
inc(x) | |
copyMem(stream, addr(buffer.data[0]), buffer.bytes) | |
# Write amplitude to own buffer, reset hardware buffer with 0, then output buffer with MixAudio() | |
proc AudioCallback_Mix(userdata: pointer; stream: ptr uint8; len: cint) {.cdecl.} = | |
for i in 0..buffer.samples - 1: | |
buffer.data[i] = Synthesis() | |
inc(x) | |
for i in 0..buffer.samples - 1: | |
cast[ptr float32](cast[int](stream) + i * BytesPerSample)[] = 0.0 | |
MixAudio(stream, cast[ptr uint8](addr(buffer.data[0])), uint32(buffer.bytes), SDL_MIX_MAXVOLUME) | |
proc main() = | |
# Init audio playback | |
if Init(INIT_AUDIO) != SdlSuccess: | |
echo("Couldn't initialize SDL\n") | |
return | |
var audioSpec: TAudioSpec | |
audioSpec.freq = cint(SampleRate) | |
audioSpec.format = AUDIO_F32 | |
audioSpec.channels = 1 | |
audioSpec.samples = uint16(BufferSizeInSamples) | |
audioSpec.padding = 0 | |
audioSpec.callback = AudioCallback_Mix | |
audioSpec.userdata = nil | |
var obtained: TAudioSpec | |
if OpenAudio(addr(audioSpec), addr(obtained)) != 0: | |
echo("Couldn't open audio device. " & $GetError() & "\n") | |
return | |
echo("frequency: ", obtained.freq) | |
echo("format: ", obtained.format) | |
echo("channels: ", obtained.channels) | |
echo("samples: ", obtained.samples) | |
echo("padding: ", obtained.padding) | |
buffer = AllocBuffer32(int(obtained.samples)) | |
# Playback audio for 2 seconds | |
PauseAudio(0) | |
Delay(2000) | |
DeallocBuffer32(buffer) | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment