AnalogTapeModel

Physical modelling signal processing for analog tape recording
Log | Files | Refs | Submodules | README | LICENSE

commit 47ada00783282572c0ba4dbdbe3ec7aec666b2a8
parent 892f1d3784ad8f347794780079cc0eaef0b64f60
Author: jatinchowdhury18 <jatinchowdhury18@users.noreply.github.com>
Date:   Sat,  9 Feb 2019 15:41:07 -0800

Basic plugin functioning

Diffstat:
MPlugin/Source/PluginProcessor.cpp | 27+++++++++------------------
MPlugin/Source/PluginProcessor.h | 4++++
MPlugin/Source/Processors/HysteresisProcessing.cpp | 2+-
MPlugin/Source/Processors/HysteresisProcessing.h | 4+++-
MSimulations/hystersis.py | 34++++++++++++++++++++--------------
5 files changed, 37 insertions(+), 34 deletions(-)

diff --git a/Plugin/Source/PluginProcessor.cpp b/Plugin/Source/PluginProcessor.cpp @@ -97,6 +97,8 @@ void ChowtapeModelAudioProcessor::prepareToPlay (double sampleRate, int samplesP { // Use this method as the place to do any pre-playback // initialisation that you need.. + hProcs[0].setSampleRate ((float) sampleRate); + hProcs[1].setSampleRate ((float) sampleRate); } void ChowtapeModelAudioProcessor::releaseResources() @@ -135,26 +137,15 @@ void ChowtapeModelAudioProcessor::processBlock (AudioBuffer<float>& buffer, Midi auto totalNumInputChannels = getTotalNumInputChannels(); auto totalNumOutputChannels = getTotalNumOutputChannels(); - // In case we have more outputs than inputs, this code clears any output - // channels that didn't contain input data, (because these aren't - // guaranteed to be empty - they may contain garbage). - // This is here to avoid people getting screaming feedback - // when they first compile a plugin, but obviously you don't need to keep - // this code if your algorithm always overwrites all the output channels. - for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i) - buffer.clear (i, 0, buffer.getNumSamples()); - - // This is the place where you'd normally do the guts of your plugin's - // audio processing... - // Make sure to reset the state if your inner loop is processing - // the samples and the outer loop is handling the channels. - // Alternatively, you can process the samples with the channels - // interleaved by keeping the same state. for (int channel = 0; channel < totalNumInputChannels; ++channel) { - auto* channelData = buffer.getWritePointer (channel); - - // ..do something to the data... + auto* x = buffer.getWritePointer (channel); + for (int n = 0; n < buffer.getNumSamples(); n++) + { + //float x_in = ((float) 1e5) * std::sinf (MathConstants<float>::twoPi * 100 * n_t[channel] / getSampleRate()); + x[n] = hProcs[channel].process (((float) 1e5) * x[n]); + //n_t[channel]++; + } } } diff --git a/Plugin/Source/PluginProcessor.h b/Plugin/Source/PluginProcessor.h @@ -11,6 +11,7 @@ #pragma once #include "../JuceLibraryCode/JuceHeader.h" +#include "Processors/HysteresisProcessing.h" //============================================================================== /** @@ -56,6 +57,9 @@ public: void setStateInformation (const void* data, int sizeInBytes) override; private: + HysteresisProcessor hProcs[2]; + int n_t[2] = { 0, 0 }; + //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChowtapeModelAudioProcessor) }; diff --git a/Plugin/Source/Processors/HysteresisProcessing.cpp b/Plugin/Source/Processors/HysteresisProcessing.cpp @@ -72,5 +72,5 @@ float HysteresisProcessor::process (float H) H_n1 = H; H_d_n1 = H_d; - return M; + return M / M_s; } diff --git a/Plugin/Source/Processors/HysteresisProcessing.h b/Plugin/Source/Processors/HysteresisProcessing.h @@ -10,6 +10,8 @@ public: float process (float H); + void setSampleRate (float newSR) { fs = newSR; } + private: float langevin (float x); @@ -26,7 +28,7 @@ private: const float k = (float) 27.0e3; const float c = (float) 1.7e-1; - float M_n1 = 0.0; + float M_n1 = 0.0f; float H_n1 = 0.0f; float H_d_n1 = 0.0f; diff --git a/Simulations/hystersis.py b/Simulations/hystersis.py @@ -2,7 +2,7 @@ import numpy as np import matplotlib.pyplot as plt from matplotlib import animation -fs = 48000 +fs = 48000 * 8 T = 1/fs # sample interval M_s = 350000 # Jiles book a = 2.2e4 #adjustable parameter @@ -28,6 +28,7 @@ def L_d (x): # trapezoidal rule derivative def deriv (x_n, x_n1, xDeriv_n1): + #return (1 / T) * (x_n - x_n1) return ((2 / T) * (x_n - x_n1)) - xDeriv_n1 # dM/dt or "non-linear function" @@ -52,40 +53,45 @@ def M_n (M_n1, k1, k2, k3, k4): return M_n1 + (k1 / 6) + (k2 / 3) + (k3 / 3) + (k4 / 6) #input signal -t = np.linspace (0, 1, fs * 50) -#H_in = (5e5) * np.sin (2 * np.pi * 100 * t) +t = np.linspace (0, 1, fs) +#t = 1 +H_in = (5e5) * np.sin (2 * np.pi * 20000 * t) freq = 2000 -H_in = np.concatenate ((5e2 * np.sin (2 * np.pi * freq * t[0:fs*5]), 1e3 * np.sin (2 * np.pi * freq * t[fs*5:fs*10]), \ - 3e3 * np.sin (2 * np.pi * freq * t[fs*10:fs*15]), 5e3 * np.sin (2 * np.pi * freq * t[fs*15:fs*20]), \ - 1e4 * np.sin (2 * np.pi * freq * t[fs*20:fs*25]), 3e4 * np.sin (2 * np.pi * freq * t[fs*25:fs*30]), \ - 5e4 * np.sin (2 * np.pi * freq * t[fs*30:fs*35]), 1e5 * np.sin (2 * np.pi * freq * t[fs*35:fs*40]), \ - 3e5 * np.sin (2 * np.pi * freq * t[fs*40:fs*45]), 5e5 * np.sin (2 * np.pi * freq * t[fs*45:fs*50]))) +#H_in = np.concatenate ((5e2 * np.sin (2 * np.pi * freq * t[0:fs*5]), 1e3 * np.sin (2 * np.pi * freq * t[fs*5:fs*10]), \ +# 3e3 * np.sin (2 * np.pi * freq * t[fs*10:fs*15]), 5e3 * np.sin (2 * np.pi * freq * t[fs*15:fs*20]), \ +# 1e4 * np.sin (2 * np.pi * freq * t[fs*20:fs*25]), 3e4 * np.sin (2 * np.pi * freq * t[fs*25:fs*30]), \ +# 5e4 * np.sin (2 * np.pi * freq * t[fs*30:fs*35]), 1e5 * np.sin (2 * np.pi * freq * t[fs*35:fs*40]), \ +# 3e5 * np.sin (2 * np.pi * freq * t[fs*40:fs*45]), 5e5 * np.sin (2 * np.pi * freq * t[fs*45:fs*50]))) +#H_in= 5e5 * np.array ([1]) # plt.plot (t, H_in) # plt.show() -M_out = np.zeros (fs * 50) +M_out = np.zeros (fs) M_n1 = 0 H_n1 = 0 H_d_n1 = 0 -H_d2_n1 = 0 n = 0 percent = 0 for H in H_in: H_d = deriv (H, H_n1, H_d_n1) - H_d2 = deriv (H_d, H_d_n1, H_d2_n1) + #print (H_d) k1 = T * f (M_n1, H_n1, H_d_n1) + #print (k1) k2 = T * f (M_n1 + k1/2, (H + H_n1) / 2, (H_d + H_d_n1) / 2) + #print (k2) k3 = T * f (M_n1 + k2/2, (H + H_n1) / 2, (H_d + H_d_n1) / 2) + #print (k3) k4 = T * f (M_n1 + k3, H, H_d) + #print (k4) M = M_n (M_n1, k1, k2, k3, k4) + #print (M) M_n1 = M H_n1 = H H_d_n1 = H_d - H_d2_n1 - H_d2 M_out[n] = M n += 1 @@ -96,12 +102,12 @@ for H in H_in: print (str (percent) + "% completed") MH = plt.figure (1) -plt.plot (H_in / 1000, M_out / M_s) +plt.plot (H_in[0:20000] / 1000, M_out[0:20000] / M_s) plt.xlabel ("Magnetic Field (A/m)") plt.ylabel ("Tape Magnetisation (A/m)") plt.title ("Simulated Ditigal Tape Magnetization Hysteresis Loop") MH.show() Mt = plt.figure (2) -plt.plot (t, M_out / M_s) +plt.plot (t[0:20000], M_out[0:20000] / M_s) plt.show()