Open Ownv94 opened 9 years ago
I just started playing with the package myself, no idea if this is the correct way to record from the input, but it works for me. I'd appreciate input from anyone familiar with the module (@ssfrr, @wherrera10, @JayKickliter, @goretkin).
using AudioIO
# Record for 11 seconds
secs = 11
type RecordingRenderer <: AudioIO.AudioRenderer
active::Bool
storage::Array{Float32}
idx::Int
function RecordingRenderer(length_s::Int)
new(false, zeros(Float32, 44100 * length_s), 1)
end
end
typealias RecordingNode AudioIO.AudioNode{RecordingRenderer}
idx = 1
import AudioIO.render
function render(node::RecordingRenderer, device_input::AudioIO.AudioBuf, info::AudioIO.DeviceInfo)
len = 1024
idx = node.idx
node.storage[idx : idx + len - 1] = device_input
node.idx += len
return device_input .* false
end
myNode = RecordingNode(secs)
println("Start recording")
AudioIO.play(myNode); sleep(secs); stop(myNode)
println("Plot recording")
using UnicodePlots
display(lineplot(1:length(myNode.renderer.storage), myNode.renderer.storage, width = 50))
println("Start playback")
sleep(1)
player = ArrayPlayer(myNode.renderer.storage)
play(player)
sleep(secs)
output...
Start recording
INFO: Initializing PortAudio. Expect errors as we scan devices
INFO: Scheduling PortAudio Render Task...
INFO: PortAudio Render Task Running...
Plot recording
┌─────────────────────────────────────────────────────────┐
0.26 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢀⠀⠀⠀⠀⠀⠀⠀⠀⡆⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⢸⠀⠀⠀⠀⠀⡀⠀⠀⡇⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⡆⢠⠀⠀⢠⣷⠀⠀⡇⢸⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣸⣿⡇⣾⣇⣴⢸⣿⡆⡇⡇⢸⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣷⣿⣿⣿⢸⣿⡇⡇⡇⢸⠀⡀⠀│
│⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣇⡇⡇⢸⠀⡇⠀│
│⣸⡆⠀⠀⠀⠀⠀⠀⢀⣀⣴⣿⣤⣿⣷⣇⡀⣄⠀⢰⠀⠀⠀⠀⠀⢀⠀⠀⠀⢰⣆⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣷⢸⣾⣧⡆│
│⣿⣿⣶⣦⠤⠤⠤⠤⢼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣾⡤⠤⠤⠤⠤⢼⣧⠤⡤⢼⣿⣶⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⣿⡇│
│⢻⡏⠀⠀⠀⠀⠀⠀⢸⡟⠿⣿⣿⣿⣿⡟⠋⠟⠁⢸⠀⠀⠀⠀⠀⠘⠁⠀⠀⢸⠟⠀⠀⠸⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢹⣿⣿⠇│
│⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠀⣿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⡇⢸⠁⡇⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⢹⣿⡇⡇⡇⢸⠀⠁⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⡟⣿⡟⢹⢸⣿⡇⡇⡇⢸⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⡇⢹⠁⠈⢸⣿⠀⡇⡇⢸⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠃⠈⠀⠀⠀⡟⠀⠃⡇⢸⠀⠀⠀│
-0.25 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠁⠀⠀⠀⠀⠀⠀⠀⠀⠇⢸⠀⠀⠀│
└─────────────────────────────────────────────────────────┘
0 490000
Start playback
That is a very nice plot!
A fork of AudioIO which I've created uses more simple functions, as in read and write. An example:
# -*- coding: utf-8 -*-
# Examples for Julia AudioIO module
using AudioIO
using WAV
CHUNKSIZE = 40960
FORMAT = AudioIO.paInt16
CHANNELS = 2
SRATE = 44100
RECORD_SECONDS = 20
"""
choose the devices for 2 channel IO
"""
function choose_input_output()
devices = get_audio_devices()
indev = -1
outdev = -1
for aud in devices
println("$(aud.device_index) $(aud.name)")
if (aud.max_input_channels == CHANNELS) & (indev == -1 )
indev = aud.device_index
end
if(aud.max_output_channels == CHANNELS) & (outdev == -1)
outdev = aud.device_index
end
end
if indev == -1
info("Appropriate input device not found.")
elseif outdev == -1
info("Appropriate output device not found.")
else
info("Using input device ", bytestring(devices[indev + 1].name),
", number ", devices[indev + 1].device_index,
" and output device ", bytestring(devices[outdev + 1].name),
", number ", devices[outdev + 1].device_index)
end
return indev, outdev
end
"""
read from input
"""
function record_audio(devnum, seconds)
instream = AudioIO.open_read(devnum, CHANNELS, SRATE, CHUNKSIZE)
bufsize = seconds * SRATE
buf = AudioIO.read(instream, bufsize)
AudioIO.Pa_CloseStream(instream.stream)
buf
end
"""
write to WAV file
"""
function write_as_WAV(buffer, filename="temp.WAV")
fio = open(filename, "w")
WAV.wavwrite(deinterlace_stereo(buffer), fio, Fs=SRATE)
end
"""
interlaced to noninterlaced stereo data
"""
function deinterlace_stereo(buffer)
reshape([buffer[1:2:end]; buffer[2:2:end]],
(floor(Int, length(buffer)/2), 2))
end
INS, OUTS = choose_input_output()
println("Starting recording...")
BUF = record_audio(INS, RECORD_SECONDS)
println("Finished reading from device number $INS")
println("Recording volume was $(mean(abs(BUF))*(100/16783))% of max")
write_as_WAV(BUF)
println("Finished writing to WAV file.")
Nice, I hadn't looked deep enough in to your fork then. But both our previous examples record and then play back. Not really suitable for the original question of real time processing.
Here is an example of processing the incoming audio in real time using Reactive.jl (@shashi) and plotting a naive level meter.
I'd love any suggestions on how to improve this acquisition code.
using AudioIO, Reactive
# Set up recording node
#
type RecordingRenderer <: AudioIO.AudioRenderer
function RecordingRenderer()
new()
end
end
typealias RecordingNode AudioIO.AudioNode{RecordingRenderer}
x = Input(convert(Float32, 0.0))
import AudioIO.render
function render(node::RecordingRenderer, device_input::AudioIO.AudioBuf, info::AudioIO.DeviceInfo)
push!(x, mean(abs(device_input)))
return device_input .* false
end
# Basic processing
#
SMA(N::Int, buffer = Float32[]) =
x -> begin
push!(buffer, x)
if length(buffer) == N+1 shift!(buffer) end
round(Int, mean(buffer))
end
moving_average = SMA(5)
# Run processing
#
myNode = RecordingNode()
println("Start recording")
AudioIO.play(myNode)
t_int = 1/20
solidglyph="█"
hist_vals = zeros(Float32, 4)
for t in 1:t_int:30
print("\u1b[1G")
print("\u1b[K")
val = moving_average(1000*value(x))
print(string(val, " |", repeat(solidglyph, val)))
sleep(t_int)
end
stop(myNode)
Output
INFO: Scheduling PortAudio Render Task...
INFO: PortAudio Render Task Running...
8 |████████
super cool, and I'm glad to see more audio-focused folks using Julia these days! There's currently an AudioInput
node defined in nodes.jl that you should be able to pipe to speakers just with play(AudioInput())
(watch out for feedback!)
One cool way to implement this would be an EnvelopeFollower node that could take any other node as input, so you could do EnvelopeFollower(AudioInput())
or EnvelopeFollower(SomeOtherNode())
I think PR #57 addresses this issue.
Excuse me, I am working about Digital Signal Processing specifically Modulation and I want to record my voice in real time but I don't know how do that. I tried to look for something in "AudioIO.jl" about my problem but nothing. Could you make some examples about how record audio in real time please ?
PD: My OS: Windows 8 and a VM: Ubuntu 14.0.4