Skip to content

Instantly share code, notes, and snippets.

@triplefox
Created December 31, 2014 02:51
Show Gist options
  • Save triplefox/62529b0463b852031121 to your computer and use it in GitHub Desktop.
Save triplefox/62529b0463b852031121 to your computer and use it in GitHub Desktop.
# 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