{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Juliaでオーディオ信号処理の練習\n", "## ワウペダル" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "process (generic function with 2 methods)" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#パターン1: BiQuadモデル可変ローパスフィルタ\n", "struct BiQuadLPF\n", " a::Vector\n", " b::Vector\n", " uz::Vector\n", " yz::Vector\n", "\n", " function BiQuadLPF()\n", " a = [1.0, 0.0, 0.0]\n", " b = [0.0, 0.0, 0.0]\n", " uz = [0.0, 0.0]\n", " yz = copy(uz)\n", " new(a, b, uz, yz)\n", " end\n", "end\n", "\n", "function setCoefficients(sys::BiQuadLPF, fc, Q, fs)\n", " ωc = 2π*fc/fs\n", " α = sin(ωc)/2Q\n", " a1 = 1 + α\n", " a2 = -2*cos(ωc)/a1\n", " a3 = (1 - α)/a1\n", " b1 = (1 - cos(ωc))/2.0/ a1\n", " b2 = b1*2\n", " b3 = b1\n", " sys.a[2] = a2\n", " sys.a[3] = a3\n", " sys.b[1] = b1\n", " sys.b[2] = b2\n", " sys.b[3] = b3\n", "end\n", "\n", "function process(sys::BiQuadLPF, u)\n", " y = sys.b[1]*u\n", " for i in [1, 2]\n", " y += sys.uz[i] * sys.b[i+1] - sys.yz[i] * sys.a[i+1]\n", " end\n", " \n", " sys.uz[2] = sys.uz[1]\n", " sys.uz[1] = u\n", " sys.yz[2] = sys.yz[1]\n", " sys.yz[1] = y\n", " \n", " return y\n", "end\n", "\n", "#mは,カットオフ周波数を時間変化させるモジュレーション信号\n", "function process!(sys::BiQuadLPF, u::Vector, m::Vector, f0, Q, fs)\n", " @assert length(u) == length(m)\n", " \n", " for i in 1:length(u)\n", " fc = f0 + m[i]\n", " setCoefficients(sys, fc, Q, fs)\n", " u[i] = process(sys, u[i])\n", " end\n", "end\n", "\n", "function process(sys::BiQuadLPF, u::Vector, m::Vector, f0, Q, fs)\n", " uc = copy(u)\n", " process!(sys, uc, m, f0, Q, fs)\n", " \n", " return uc\n", "end" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "process (generic function with 4 methods)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#パターン2: StateVariableモデル可変ローパスフィルタ\n", "struct StateVariableLPF\n", " s::Vector\n", "\n", " StateVariableLPF() = new([0.0, 0.0])\n", "end\n", "\n", "function process(sys::StateVariableLPF, u, g, Q)\n", " den = 1 + g/Q + g^2\n", " G1 = g/den\n", " S1 = (sys.s[1] - g*sys.s[2])/den\n", " G2 = g*G1\n", " S2 = g*S1 + sys.s[2]\n", " \n", " ξ = u - 1.0/Q * (G1*u + S1) - (G2*u + S2)\n", " v = g*ξ\n", " y1 = v + sys.s[1]\n", " sys.s[1] = v + y1\n", " \n", " v = g*y1\n", " y2 = v + sys.s[2]\n", " sys.s[2] = v + y2\n", " \n", " return y2\n", "end\n", "\n", "function process!(sys::StateVariableLPF, u::Vector, m::Vector, f0, Q, fs)\n", " @assert length(u) == length(m)\n", " \n", " for i in 1:length(u)\n", " fc = f0 + m[i]\n", " g = π*fc/fs\n", " u[i] = process(sys, u[i], g, Q)\n", " end\n", "end\n", "\n", "function process(sys::StateVariableLPF, u::Vector, m::Vector, f0, Q, fs)\n", " uc = copy(u)\n", " process!(sys, uc, m, f0, Q, fs)\n", " \n", " return uc\n", "end" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#オーディオファイルIOパッケージ\n", "using LibSndFile" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "

SampleBuf display requires javascript

\n", "

To enable for the whole notebook select \"Trust Notebook\" from the\n", " \"File\" menu. You can also trust this cell by re-running it. You may\n", " also need to re-run `using SampledSignals` if the module is not yet\n", " loaded in the Julia kernel, or `SampledSignals.embed_javascript()`\n", " if the Julia module is loaded but the javascript isn't initialized.

\n", "
\n", "\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "705600-frame, 2-channel SampleBuf{FixedPointNumbers.Fixed{Int16,15}, 2}\n", "16.0s sampled at 44100.0Hz\n", "▇▇▇▇▇▇▇▇▇▇▅▇▇▇▇▆▅▄▄▄▇▇▇▇▇▇▇▇▇▇▅▇▇▇▇▆▅▄▄▄▇▇▇▇▇▇▇▇▇▆▇▇▆▇▇▇▆▇▇▆▇▇▇▇▇▇▇▇▇▆▇▇▆▇▇▇▆▇▇▆\n", "▇▇▇▇▇▇▇▇▇▇▅▇▇▇▇▅▅▅▄▃▇▇▇▇▇▇▇▇▇▇▅▇▇▇▇▅▅▅▄▃▇▇▇▇▇▇▇▇▇▆▇▇▇▇▇▇▆▇▇▆▇▇▇▇▇▇▇▇▇▆▇▇▇▇▇▇▆▇▇▆" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#サンプルオーディオデータ\n", "audio = load(\"./Resource/SynthSample.wav\")" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 1.274777 seconds (20.48 M allocations: 377.991 MiB, 10.65% gc time)\n", " 1.108399 seconds (20.46 M allocations: 376.831 MiB, 3.42% gc time)\n" ] }, { "data": { "text/html": [ "
\n", "

SampleBuf display requires javascript

\n", "

To enable for the whole notebook select \"Trust Notebook\" from the\n", " \"File\" menu. You can also trust this cell by re-running it. You may\n", " also need to re-run `using SampledSignals` if the module is not yet\n", " loaded in the Julia kernel, or `SampledSignals.embed_javascript()`\n", " if the Julia module is loaded but the javascript isn't initialized.

\n", "
\n", "\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "705600-frame, 2-channel SampleBuf{Float64, 2}\n", "16.0s sampled at 44100.0Hz\n", "▇▇▇▇▇▇█▇▇▇▆█▇▇▇▆▆▄▄▄▇▇▇▇▇▇█▇▇▇▆█▇▇▇▆▆▄▄▄▇▇▇▇▇▇▇█▇▆▇▇▇█▇▇▆▇▇▇▇▇▇▇▇▇▇█▇▆▇▇▇█▇▇▆▇▇▇\n", "▇▇▇▇▇▇▇█▇▇▆▇▇██▅▅▅▄▃▇▇▇▇▇▇▇█▇▇▆▇▇██▅▅▅▄▃▇▇▇▇▇▇▇█▇▆▇▇▇▇▇▇▆▇▇▇▇▇▇▇▇▇▇█▇▆▇▇▇▇▇▇▆▇▇▇" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#ワウエフェクトのパラメータ設定\n", "fs = audio.samplerate\n", "f0 = 1000.0\n", "Q = 3.0\n", "\n", "#モジュレーション信号の生成\n", "fm = 7.5\n", "A = 600.0\n", "n = 0:length(audio.data[:, 1])-1\n", "m = A*sin.(2π*fm / fs * n)\n", "\n", "#BiQuadフィルタによるワウ\n", "bqf = [BiQuadLPF(), BiQuadLPF()]\n", "faudio = convert(Array{Float64}, audio.data)\n", "@time left = process(bqf[1], faudio[:, 1], m, f0, Q, fs)\n", "@time right = process(bqf[2], faudio[:, 2], m, f0, Q, fs)\n", "SampledSignals.SampleBuf([left right], fs)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 1.004097 seconds (21.88 M allocations: 344.834 MiB, 11.53% gc time)\n", " 0.844565 seconds (21.87 M allocations: 344.532 MiB, 1.47% gc time)\n" ] }, { "data": { "text/html": [ "
\n", "

SampleBuf display requires javascript

\n", "

To enable for the whole notebook select \"Trust Notebook\" from the\n", " \"File\" menu. You can also trust this cell by re-running it. You may\n", " also need to re-run `using SampledSignals` if the module is not yet\n", " loaded in the Julia kernel, or `SampledSignals.embed_javascript()`\n", " if the Julia module is loaded but the javascript isn't initialized.

\n", "
\n", "\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "705600-frame, 2-channel SampleBuf{Float64, 2}\n", "16.0s sampled at 44100.0Hz\n", "▇▇▇▇▇▇█▇▇▇▆█▇▇▇▆▆▄▄▄▇▇▇▇▇▇█▇▇▇▆█▇▇▇▆▆▄▄▄▇▇▇▇▇▇▇█▇▆▇▇▇█▇▇▆▇▇▇▇▇▇▇▇▇▇█▇▆▇▇▇█▇▇▆▇▇▇\n", "▇▇▇▇▇▇▇█▇▇▆▇▇██▅▅▅▄▃▇▇▇▇▇▇▇█▇▇▆▇▇██▅▅▅▄▃▇▇▇▇▇▇▇█▇▆▇▇▇▇▇▇▆▇▇▇▇▇▇▇▇▇▇█▇▆▇▇▇▇▇▇▆▇▇▇" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#StateVariableフィルタによるワウ\n", "svf = [StateVariableLPF(), StateVariableLPF()]\n", "faudio = convert(Array{Float64}, audio.data)\n", "@time left = process(svf[1], faudio[:, 1], m, f0, Q, fs)\n", "@time right = process(svf[2], faudio[:, 2], m, f0, Q, fs)\n", "SampledSignals.SampleBuf([left right], fs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 参考文献\n", "BiQadu filterについて \n", "[1] R. B. Jhonson: Cookbook formulae for audio EQ biquad filter coefficients [Online], Accessed 10 Mar. 2018.[Link](http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt) \n", "\n", "State variable filterについて \n", "[2] V. Zavalishin: THE ART OF VA FILTER DESIGN [Online], 2015, Accessed 10 Mar. 2018. [Link](https://www.native-instruments.com/fileadmin/ni_media/downloads/pdf/VAFilterDesign_1.1.1.pdf) \n", "[3] J. O. Smith: Digital State-Variable Filters [Online], Accessed 10 Mar. 2018. [Link](https://ccrma.stanford.edu/~jos/svf/)" ] } ], "metadata": { "kernelspec": { "display_name": "Julia 0.6.2", "language": "julia", "name": "julia-0.6" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "0.6.2" } }, "nbformat": 4, "nbformat_minor": 2 }