Created
May 18, 2023 11:40
-
-
Save amb/0f06f2e69490df5e07890ff8b65fd271 to your computer and use it in GitHub Desktop.
Simple Bytebeat in Nim+portaudio
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
# 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