次のパッケージを使用する
SampledSignals.jl ファイルから読み込んだ/録音したオーディオデータを保持する構造体が定義されている
LibSndFile.jl オーディオファイルIO.wav,mp3,FLAC等いろいろ読める.
PortAudio.jl マイク入力を録音したり,処理したり.
using SampledSignals
#サンプリングレート48 kHzで周波数440 Hzのサイン波 2秒分のデータを用意
fs = 48000.0
n = [i for i in 0:96000]
wavedata = sin.(2π*440.0*n/fs)
#生成したデータからSampleBufインスタンスを生成
buf = SampleBuf(wavedata, fs)
To enable for the whole notebook select "Trust Notebook" from the "File" menu. You can also trust this cell by re-running it. You may also need to re-run `using SampledSignals` if the module is not yet loaded in the Julia kernel, or `SampledSignals.embed_javascript()` if the Julia module is loaded but the javascript isn't initialized.
SampleBuf構造体がオーディオデータを保持する.
SampleBuf.samplerate,SampleBuf.dataとして,サンプルレート,オーディオデータを保持.
オーディオデータの振幅は,[-1.0, 1.0]の範囲(正確には1.0は含まれないが詳細は省略).|1.0|より大きいとクリップ.
SampleBufインスタンスをCellの出力にすると,Jupyter上ですぐに音を聞くことができる
#ステレオも可能
#サンプルデータ*チャンネルつまりWaveLength*2の行列からSampleBufを作ればOK
leftwave = wavedata
rightwave = 0.2*wavedata
stereodata = [leftwave rightwave]
stereobuf = SampleBuf(stereodata, fs)
To enable for the whole notebook select "Trust Notebook" from the "File" menu. You can also trust this cell by re-running it. You may also need to re-run `using SampledSignals` if the module is not yet loaded in the Julia kernel, or `SampledSignals.embed_javascript()` if the Julia module is loaded but the javascript isn't initialized.
using LibSndFile
drumloop = load("./Resource/AudioSample.wav")
@show typeof(drumloop)
drumloop
typeof(drumloop) = SampledSignals.SampleBuf{FixedPointNumbers.Fixed{Int16,15},2}
To enable for the whole notebook select "Trust Notebook" from the "File" menu. You can also trust this cell by re-running it. You may also need to re-run `using SampledSignals` if the module is not yet loaded in the Julia kernel, or `SampledSignals.embed_javascript()` if the Julia module is loaded but the javascript isn't initialized.
読み込んだオーディオファイルのデータはSampleBufインスタンスとして返される
従って,Jupyter上ですぐに再生可能
先のドラムループの左チャンネルだけをノーマライズしてみる
stereodrum = convert(Array{Float64}, drumloop.data)
480000×2 Array{Float64,2}: 0.000244141 0.000335693 0.000732422 0.000854492 0.00131226 0.00152588 0.00338745 0.00366211 0.00619507 0.00646973 0.00479126 0.00509644 -0.00363159 -0.0032959 -0.0126038 -0.0122375 -0.0128784 -0.0123901 -0.00317383 -0.00265503 0.00912476 0.00970459 0.0169373 0.0175781 0.0152283 0.0159912 ⋮ 0.0 0.0 3.05176e-5 3.05176e-5 -3.05176e-5 -3.05176e-5 3.05176e-5 3.05176e-5 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3.05176e-5 3.05176e-5 0.0 0.0 0.0 0.0 0.0 0.0
オーディオフィルから読んだデータは,FixedPointNumbers.Fixed型
小数点以下の桁数が固定された小数(らしい)
そのまま,Float32/64と混ぜて計算できるけど,一応,先に型変換しておく
leftdata = stereodrum[:, 1]
rightdata = stereodrum[:, 2]
maxval, minval = extrema(leftdata)
normalizeco = maximum([abs(maxval), abs(minval)])
leftdata = leftdata/normalizeco
normalizeddata = [leftdata rightdata]
normalizeddrum = SampleBuf(normalizeddata, drumloop.samplerate)
To enable for the whole notebook select "Trust Notebook" from the "File" menu. You can also trust this cell by re-running it. You may also need to re-run `using SampledSignals` if the module is not yet loaded in the Julia kernel, or `SampledSignals.embed_javascript()` if the Julia module is loaded but the javascript isn't initialized.
(そういえば,組み込みのnormalize関数があったか...?)
これ以降のコードは一部,nbviewer上だと一部動作しないのでローカルで試してみてください
using PortAudio
InitError: MethodError: no method matching redirect_stderr(::IJulia.IJuliaStdio{Base.PipeEndpoint}) Closest candidates are: redirect_stderr() at stream.jl:1034 redirect_stderr(::Union{Base.LibuvStream, IOStream}) at stream.jl:1028 redirect_stderr(::Function, ::Any) at stream.jl:1082 during initialization of module PortAudio Stacktrace: [1] macro expansion at C:\Julia\PKG\v0.6\PortAudio\src\suppressor.jl:15 [inlined] [2] __init__() at C:\Julia\PKG\v0.6\PortAudio\src\PortAudio.jl:23 [3] _include_from_serialized(::String) at .\loading.jl:157 [4] _require_from_serialized(::Int64, ::Symbol, ::String, ::Bool) at .\loading.jl:200 [5] _require_search_from_serialized(::Int64, ::Symbol, ::String, ::Bool) at .\loading.jl:236 [6] _require(::Symbol) at .\loading.jl:441 [7] require(::Symbol) at .\loading.jl:405 [8] include_string(::String, ::String) at .\loading.jl:522
jupyter上だとusing PortAudio時にエラー吐くけど,今のところ録音時に問題は確認できてないのでこのまま続けます.
外付けAudio IFに使われているASIOドライバ等は認識できないので,Audio IFを使っている人は既定の録音・再生デバイスをデフォルトのサウンドカードにしておいてください.
stream = PortAudio.PortAudioStream(1, 0)
1in/0outのストリームを作成.(とりあえず録音だけなので). マイク入力を拾えるようになる
#このCellを実行すると5秒間マイクの音を録音開始
#録音データはSampleBufインスタンスとして返ってくるので,再生プレイヤーが立ち上がる
recbuf = read(stream, 5s)
To enable for the whole notebook select "Trust Notebook" from the "File" menu. You can also trust this cell by re-running it. You may also need to re-run `using SampledSignals` if the module is not yet loaded in the Julia kernel, or `SampledSignals.embed_javascript()` if the Julia module is loaded but the javascript isn't initialized.
ノートPCのマイクで録音したせいかノイズがひどい...
stream = PortAudio.PortAudioStream(1, 1, synced=true)
@show stream.blocksize
stream.blocksize = 4096
1in/1outのストリームを作成.synced=trueで入出力バッファの同期がとれる.
#マイク入力にリアルタイムでトレモロをかけてみる
L = stream.blocksize
fs = stream.samplerate
n = 0
for i in 1:100
#blocksize分の入力サンプルを処理して出力するという操作を繰り返す(=blocksize * 100 / fs秒分行う)
inbuff = read(stream, L)
audiodata = convert(Array{Float32}, inbuff.data[:, 1])
for j in 1:L
audiodata[j] = audiodata[j]*sin(2π*5.0*n/fs)
n += 1
end
outbuff = SampledSignals.SampleBuf(audiodata, fs)
write(stream, outbuff, L)
end