Skip to content

Instantly share code, notes, and snippets.

@amb
Created May 18, 2023 11:40
Show Gist options
  • Save amb/0f06f2e69490df5e07890ff8b65fd271 to your computer and use it in GitHub Desktop.
Save amb/0f06f2e69490df5e07890ff8b65fd271 to your computer and use it in GitHub Desktop.
Simple Bytebeat in Nim+portaudio
# For Windows add following to nim.cfg (in user/.choosenim/toolchains/nim-x.y.z/config/)
# Line ~159: gcc.path = r"C:\tools\msys64\mingw64\bin"
import os, math
import nordaudio
const
# SAMPLE_RATE = 44100
SAMPLE_RATE = 8000
FRAMES_PER_BUFFER = 64
PLAY_TIME = 60 * 8 + 44
TABLE_SIZE = SAMPLE_RATE * PLAY_TIME
type
TestData = object
audiodata: array[TABLE_SIZE, float32]
left_phase: int
right_phase: int
time: int
proc callback(output: var openarray[float32], data: var TestData) =
for i in countup(0, output.len-1, 2):
output[i] = 0.5 * data.audiodata[data.left_phase]
output[i+1] = 0.5 * data.audiodata[data.right_phase]
inc(data.left_phase, 1)
if data.left_phase >= TABLE_SIZE:
dec(data.left_phase, TABLE_SIZE)
inc(data.right_phase, 1)
if data.right_phase >= TABLE_SIZE:
dec(data.right_phase, TABLE_SIZE)
inc data.time
proc cCallback*(inputBuffer: pointer; outputBuffer: pointer;
framesPerBuffer: culong;
timeInfo: ptr StreamCallbackTimeInfo;
statusFlags: StreamCallbackFlags; userData: pointer): cint {.cdecl.} =
var data = cast[ptr TestData](userData)
var tmp = cast[ptr UncheckedArray[float32]](outputBuffer)
callback(toOpenArray(tmp, 0, 2*cast[int](framesPerBuffer)-1), data[])
return 0
var
outputParameters: StreamParameters
stream: ptr Stream
data: TestData
# http://canonical.org/~kragen/bytebeat/
# "crowd" by viznut
for i in 0..<TABLE_SIZE:
let t = i.uint32
var smp: uint8 = (((t shl 1) xor ((t shl 1)+(t shr 7) and t shr 12)) or
(t shr (4-(1 xor 7 and (t shr 19))) or t shr 7)).uint8
data.audiodata[i] = (float32(smp) / 255.0 - 0.5) * 2.0
data.left_phase = 0
data.right_phase = 0
data.time = 0
discard initialize()
outputParameters.device = getDefaultOutputDevice()
outputParameters.channelCount = 2
outputParameters.sampleFormat = paFloat32
outputParameters.suggestedLatency = getDeviceInfo(outputParameters.device).defaultLowOutputLatency
outputParameters.hostApiSpecificStreamInfo = nil
discard openStream(addr(stream), nil, addr(outputParameters), SAMPLE_RATE, FRAMES_PER_BUFFER,
paClipOff, cCallback, addr(data))
discard startStream(stream)
sleep(1000)
echo "CPU load:", getStreamCpuLoad(stream)
echo "Stream time:", getStreamTime(stream)
sleep(PLAY_TIME*1000-1000)
discard stopStream(stream)
discard closeStream(stream)
discard terminate()
echo "success."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment