# HG changeset patch # User Brecht De Man # Date 1448205820 0 # Node ID 04e171d2a747b1819042458805be3df38d23384a # Parent e32fe563e12451fb39d3f2d9a9ad4c4b2fa53d6c JUCE 4 compatible. Standardised paths on Mac: modules '../../juce/modules'; VST folder '~/SDKs/vstsdk2.4' (JUCE default). Replaced deprecated 'getSampleData(channel)'; getToggleState(...); setToggleState(...); setSelectedId(...). Removed unused variables. Ignore JUCE code and build files. diff -r e32fe563e124 -r 04e171d2a747 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sun Nov 22 15:23:40 2015 +0000 @@ -0,0 +1,4 @@ +syntax: glob +effects/*/Builds/* +juce +effects/*/JuceLibraryCode/* \ No newline at end of file diff -r e32fe563e124 -r 04e171d2a747 effects/autowah/Source/PluginProcessor.cpp --- a/effects/autowah/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/autowah/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -281,7 +281,7 @@ for(channel = 0; channel < jmin(numInputChannels, numWahFilters_); ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); ph = lfoPhase_; for (int sample = 0; sample < numSamples; ++sample) diff -r e32fe563e124 -r 04e171d2a747 effects/autowah/autowah.jucer --- a/effects/autowah/autowah.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/autowah/autowah.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -1,13 +1,13 @@ @@ -68,4 +68,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/chorus/Source/PluginEditor.cpp --- a/effects/chorus/Source/PluginEditor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/chorus/Source/PluginEditor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -165,10 +165,10 @@ sweepWidthSlider_.setValue(ourProcessor->sweepWidth_, dontSendNotification); depthSlider_.setValue(ourProcessor->depth_, dontSendNotification); frequencySlider_.setValue(ourProcessor->frequency_, dontSendNotification); - waveformComboBox_.setSelectedId(ourProcessor->waveform_, false); - interpolationComboBox_.setSelectedId(ourProcessor->interpolation_, false); - numVoicesComboBox_.setSelectedId(ourProcessor->numVoices_, false); - stereoToggleButton_.setToggleState((ourProcessor->stereo_ != 0), false); + waveformComboBox_.setSelectedId(ourProcessor->waveform_, dontSendNotification); + interpolationComboBox_.setSelectedId(ourProcessor->interpolation_, dontSendNotification); + numVoicesComboBox_.setSelectedId(ourProcessor->numVoices_, dontSendNotification); + stereoToggleButton_.setToggleState((ourProcessor->stereo_ != 0), dontSendNotification); } // This is our Slider::Listener callback, when the user drags a slider. diff -r e32fe563e124 -r 04e171d2a747 effects/chorus/Source/PluginProcessor.cpp --- a/effects/chorus/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/chorus/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -274,10 +274,10 @@ for (channel = 0; channel < numInputChannels; ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); // delayData is the circular buffer for implementing delay on this channel - float* delayData = delayBuffer_.getSampleData (jmin (channel, delayBuffer_.getNumChannels() - 1)); + float* delayData = delayBuffer_.getWritePointer (jmin (channel, delayBuffer_.getNumChannels() - 1)); // Make a temporary copy of any state variables declared in PluginProcessor.h which need to be // maintained between calls to processBlock(). Each channel needs to be processed identically diff -r e32fe563e124 -r 04e171d2a747 effects/chorus/chorus.jucer --- a/effects/chorus/chorus.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/chorus/chorus.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -7,12 +7,13 @@ pluginCode="chor" pluginChannelConfigs="{2,2}, {1,1}" pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="0" pluginTailLength="1" pluginEditorRequiresKeys="0" pluginAUExportPrefix="chorusAU" - pluginAUViewClass="chorusAU_V1" pluginRTASCategory="" jucerVersion="3.1.0" + pluginAUViewClass="chorusAU_V1" pluginRTASCategory="" jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.chorus" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + @@ -63,4 +64,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/compressor/Compressor.jucer --- a/effects/compressor/Compressor.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/compressor/Compressor.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -7,7 +7,7 @@ pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="CompressorAU" pluginAUViewClass="CompressorAU_V1" - pluginRTASCategory="" jucerVersion="3.1.0" aaxIdentifier="uk.ac.qmul.eecs.compressor" + pluginRTASCategory="" jucerVersion="4.0.2" aaxIdentifier="uk.ac.qmul.eecs.compressor" buildVST3="0" buildAAX="0" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1" companyName="Reiss and McPherson"> @@ -33,7 +33,7 @@ - + @@ -86,4 +86,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/compressor/Source/PluginEditor.cpp --- a/effects/compressor/Source/PluginEditor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/compressor/Source/PluginEditor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -287,8 +287,8 @@ { // Display the ON/OFF button in its correct state - if (buttonONOFF->getToggleState()) buttonONOFF->setToggleState(true, false); - else buttonONOFF->setToggleState(false, false); + if (buttonONOFF->getToggleState()) buttonONOFF->setToggleState(true, dontSendNotification); + else buttonONOFF->setToggleState(false, dontSendNotification); } diff -r e32fe563e124 -r 04e171d2a747 effects/compressor/Source/PluginProcessor.cpp --- a/effects/compressor/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/compressor/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -29,7 +29,6 @@ #include "PluginProcessor.h" #include "PluginEditor.h" -const float tau = 200; CompressorAudioProcessor::CompressorAudioProcessor() // Initializer List : @@ -84,8 +83,8 @@ // apply control voltage to the audio signal for (int i = 0 ; i < bufferSize ; ++i) { - buffer.getSampleData(2*m+0)[i] *= c[i]; - buffer.getSampleData(2*m+1)[i] *= c[i]; + buffer.getWritePointer(2*m+0)[i] *= c[i]; + buffer.getWritePointer(2*m+1)[i] *= c[i]; } inputBuffer.clear(m,0,bufferSize); // Mix down left-right to analyse the output @@ -103,8 +102,8 @@ for (int i = 0 ; i < bufferSize ; ++i) { //Level detection- estimate level using peak detector - if (fabs(buffer.getSampleData(m)[i]) < 0.000001) x_g[i] =-120; - else x_g[i] =20*log10(fabs(buffer.getSampleData(m)[i])); + if (fabs(buffer.getWritePointer(m)[i]) < 0.000001) x_g[i] =-120; + else x_g[i] =20*log10(fabs(buffer.getWritePointer(m)[i])); //Gain computer- static apply input/output curve if (x_g[i] >= threshold) y_g[i] = threshold+ (x_g[i] - threshold) / ratio; else y_g[i] = x_g[i]; diff -r e32fe563e124 -r 04e171d2a747 effects/delay/Source/PluginProcessor.cpp --- a/effects/delay/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/delay/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -247,10 +247,10 @@ for (channel = 0; channel < numInputChannels; ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); // delayData is the circular buffer for implementing delay on this channel - float* delayData = delayBuffer_.getSampleData (jmin (channel, delayBuffer_.getNumChannels() - 1)); + float* delayData = delayBuffer_.getWritePointer (jmin (channel, delayBuffer_.getNumChannels() - 1)); // Make a temporary copy of any state variables declared in PluginProcessor.h which need to be // maintained between calls to processBlock(). Each channel needs to be processed identically diff -r e32fe563e124 -r 04e171d2a747 effects/delay/delay.jucer --- a/effects/delay/delay.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/delay/delay.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -7,12 +7,13 @@ pluginCode="dlay" pluginChannelConfigs="{1, 1}, {2, 2}" pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="0" pluginTailLength="2" pluginEditorRequiresKeys="0" pluginAUExportPrefix="delayAU" - pluginAUViewClass="delayAU_V1" pluginRTASCategory="" jucerVersion="3.1.0" + pluginAUViewClass="delayAU_V1" pluginRTASCategory="" jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.delay" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + @@ -63,4 +64,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/distortion/Source/PluginProcessor.cpp --- a/effects/distortion/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/distortion/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -36,8 +36,6 @@ #include "PluginProcessor.h" #include "PluginEditor.h" -const float DENORMAL_THRESH = 1e-6f; - #if JUCE_INTEL #define JUCE_SNAP_TO_ZERO(n) if (! (n < -1.0e-8 || n > 1.0e-8)) n = 0; #else @@ -90,7 +88,7 @@ // Put track audio data into _currentTrackBuffer float * originalData = new float; - originalData = buffer.getSampleData(channel); + originalData = buffer.getWritePointer(channel); // Apply distortion (sample per sample) switch (_typeNumber) { diff -r e32fe563e124 -r 04e171d2a747 effects/distortion/distortion.jucer --- a/effects/distortion/distortion.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/distortion/distortion.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -8,11 +8,11 @@ pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="distortionAU" pluginAUViewClass="MasterCompressorAU_V1" pluginRTASCategory="" - jucerVersion="3.1.0" aaxIdentifier="uk.ac.qmul.eecs.distortioneffect" + jucerVersion="4.0.2" aaxIdentifier="uk.ac.qmul.eecs.distortioneffect" pluginAAXCategory="" includeBinaryInAppConfig="1" buildVST3="0" buildAAX="0" companyName="Reiss and McPherson"> - + @@ -61,4 +61,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/empty/Source/PluginProcessor.cpp --- a/effects/empty/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/empty/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -199,7 +199,7 @@ for (int channel = 0; channel < numInputChannels; ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); for (int i = 0; i < numSamples; ++i) { diff -r e32fe563e124 -r 04e171d2a747 effects/empty/empty.jucer --- a/effects/empty/empty.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/empty/empty.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -7,12 +7,13 @@ pluginCode="empt" pluginChannelConfigs="{1, 1}, {2, 2}" pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="emptyAU" - pluginAUViewClass="emptyAU_V1" pluginRTASCategory="" jucerVersion="3.1.0" + pluginAUViewClass="emptyAU_V1" pluginRTASCategory="" jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.empty" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + @@ -63,4 +64,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/flanger/Source/PluginEditor.cpp --- a/effects/flanger/Source/PluginEditor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/flanger/Source/PluginEditor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -162,9 +162,9 @@ depthSlider_.setValue(ourProcessor->depth_, dontSendNotification); feedbackSlider_.setValue(ourProcessor->feedback_, dontSendNotification); frequencySlider_.setValue(ourProcessor->frequency_, dontSendNotification); - waveformComboBox_.setSelectedId(ourProcessor->waveform_, false); - interpolationComboBox_.setSelectedId(ourProcessor->interpolation_, false); - stereoToggleButton_.setToggleState((ourProcessor->stereo_ != 0), false); + waveformComboBox_.setSelectedId(ourProcessor->waveform_, dontSendNotification); + interpolationComboBox_.setSelectedId(ourProcessor->interpolation_, dontSendNotification); + stereoToggleButton_.setToggleState((ourProcessor->stereo_ != 0), dontSendNotification); } // This is our Slider::Listener callback, when the user drags a slider. diff -r e32fe563e124 -r 04e171d2a747 effects/flanger/Source/PluginProcessor.cpp --- a/effects/flanger/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/flanger/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -275,10 +275,10 @@ for (channel = 0; channel < numInputChannels; ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); // delayData is the circular buffer for implementing delay on this channel - float* delayData = delayBuffer_.getSampleData (jmin (channel, delayBuffer_.getNumChannels() - 1)); + float* delayData = delayBuffer_.getWritePointer (jmin (channel, delayBuffer_.getNumChannels() - 1)); // Make a temporary copy of any state variables declared in PluginProcessor.h which need to be // maintained between calls to processBlock(). Each channel needs to be processed identically diff -r e32fe563e124 -r 04e171d2a747 effects/flanger/flanger.jucer --- a/effects/flanger/flanger.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/flanger/flanger.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -7,12 +7,13 @@ pluginCode="flng" pluginChannelConfigs="{2,2},{1,1}" pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="flangerAU" - pluginAUViewClass="flangerAU_V1" pluginRTASCategory="" jucerVersion="3.1.0" + pluginAUViewClass="flangerAU_V1" pluginRTASCategory="" jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.flanger" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + @@ -63,4 +64,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/parametriceq/Source/PluginProcessor.cpp --- a/effects/parametriceq/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/parametriceq/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -238,7 +238,7 @@ for (channel = 0; channel < jmin((int32)numInputChannels, numEqFilters_); ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); // Run the samples through the IIR filter whose coefficients define the parametric // equaliser. See juce_IIRFilter.cpp for the implementation. diff -r e32fe563e124 -r 04e171d2a747 effects/parametriceq/parametriceq.jucer --- a/effects/parametriceq/parametriceq.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/parametriceq/parametriceq.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -7,12 +7,13 @@ pluginCode="pmeq" pluginChannelConfigs="{1, 1}, {2, 2}" pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="parametriceqAU" - pluginAUViewClass="parametriceqAU_V1" pluginRTASCategory="" jucerVersion="3.1.0" + pluginAUViewClass="parametriceqAU_V1" pluginRTASCategory="" jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.parametriceq" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + @@ -67,4 +68,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/phaser/Source/OnePoleAllpassFilter.h --- a/effects/phaser/Source/OnePoleAllpassFilter.h Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/phaser/Source/OnePoleAllpassFilter.h Sun Nov 22 15:23:40 2015 +0000 @@ -1,77 +1,77 @@ -/* - This code accompanies the textbook: - - Digital Audio Effects: Theory, Implementation and Application - Joshua D. Reiss and Andrew P. McPherson - - --- - - Phaser: phasing effect using time-varying allpass filters - See textbook Chapter 4: Filter Effects - - Code by Andrew McPherson, Brecht De Man and Joshua Reiss - - --- - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef __ONEPOLEALLPASSFILTER_H_6E48F605__ -#define __ONEPOLEALLPASSFILTER_H_6E48F605__ - -#define _USE_MATH_DEFINES -#include "../JuceLibraryCode/JuceHeader.h" - -/** - * This class implements a 1st-order allpass filter used in the phaser effect. - * Unlike TwoPoleAllpassFilter, it does not extend IIRFilter which is two-pole. - * Loosely modelled after OnePoleFilter.cpp by dRowAudio. - */ - -class OnePoleAllpassFilter -{ -public: - //============================================================================== - // Create an unititialised filter. - // This will not perform any filtering until the allpass coefficients have been set. - OnePoleAllpassFilter() noexcept; - - // Destructor. - ~OnePoleAllpassFilter() noexcept; - - //Process a number of samples in one go. - // This is the most effecient method of filtering. - // Note that the samples passed to it actually get changed. - void processSamples (float* const samples, - const int numSamples) noexcept; - - // Process a single sample. - // Less efficient method but leaves the sample unchanged, - // returning a filtered copy of it. - float processSingleSampleRaw (const float sampleToProcess) noexcept; - - // Set the centre frequency of the allpass with respect to the sample rate - void makeAllpass (const double inverseSampleRate, - const double centreFrequency) noexcept; - -private: - //============================================================================== - CriticalSection lock; - float x1, y1, b0, b1, a1; - - //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OnePoleAllpassFilter); -}; - -#endif /* __ONEPOLEALLPASSFILTER_H_6E48F605__ */ +/* + This code accompanies the textbook: + + Digital Audio Effects: Theory, Implementation and Application + Joshua D. Reiss and Andrew P. McPherson + + --- + + Phaser: phasing effect using time-varying allpass filters + See textbook Chapter 4: Filter Effects + + Code by Andrew McPherson, Brecht De Man and Joshua Reiss + + --- + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __ONEPOLEALLPASSFILTER_H_6E48F605__ +#define __ONEPOLEALLPASSFILTER_H_6E48F605__ + +#define _USE_MATH_DEFINES +#include "../JuceLibraryCode/JuceHeader.h" + +/** + * This class implements a 1st-order allpass filter used in the phaser effect. + * Unlike TwoPoleAllpassFilter, it does not extend IIRFilter which is two-pole. + * Loosely modelled after OnePoleFilter.cpp by dRowAudio. + */ + +class OnePoleAllpassFilter +{ +public: + //============================================================================== + // Create an unititialised filter. + // This will not perform any filtering until the allpass coefficients have been set. + OnePoleAllpassFilter() noexcept; + + // Destructor. + ~OnePoleAllpassFilter() noexcept; + + //Process a number of samples in one go. + // This is the most effecient method of filtering. + // Note that the samples passed to it actually get changed. + void processSamples (float* const samples, + const int numSamples) noexcept; + + // Process a single sample. + // Less efficient method but leaves the sample unchanged, + // returning a filtered copy of it. + float processSingleSampleRaw (const float sampleToProcess) noexcept; + + // Set the centre frequency of the allpass with respect to the sample rate + void makeAllpass (const double inverseSampleRate, + const double centreFrequency) noexcept; + +private: + //============================================================================== + CriticalSection lock; + float x1, y1, b0, b1, a1; + + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OnePoleAllpassFilter); +}; + +#endif /* __ONEPOLEALLPASSFILTER_H_6E48F605__ */ diff -r e32fe563e124 -r 04e171d2a747 effects/phaser/Source/PluginEditor.cpp --- a/effects/phaser/Source/PluginEditor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/phaser/Source/PluginEditor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -164,9 +164,9 @@ depthSlider_.setValue(ourProcessor->depth_, dontSendNotification); feedbackSlider_.setValue(ourProcessor->feedback_, dontSendNotification); lfoFrequencySlider_.setValue(ourProcessor->lfoFrequency_, dontSendNotification); - waveformComboBox_.setSelectedId(ourProcessor->waveform_, false); - filtersComboBox_.setSelectedId(ourProcessor->filtersPerChannel_, false); - stereoToggleButton_.setToggleState((ourProcessor->stereo_ != 0), false); + waveformComboBox_.setSelectedId(ourProcessor->waveform_, dontSendNotification); + filtersComboBox_.setSelectedId(ourProcessor->filtersPerChannel_, dontSendNotification); + stereoToggleButton_.setToggleState((ourProcessor->stereo_ != 0), dontSendNotification); } // This is our Slider::Listener callback, when the user drags a slider. diff -r e32fe563e124 -r 04e171d2a747 effects/phaser/Source/PluginProcessor.cpp --- a/effects/phaser/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/phaser/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -281,7 +281,7 @@ for(int channel = 0; channel < numInputChannels; ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); ph = lfoPhase_; sc = sampleCount_; diff -r e32fe563e124 -r 04e171d2a747 effects/phaser/phaser.jucer --- a/effects/phaser/phaser.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/phaser/phaser.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -7,11 +7,11 @@ pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="phaserAU" pluginAUViewClass="phaserAU_V1" - pluginRTASCategory="" jucerVersion="3.1.0" companyName="Reiss and McPherson" + pluginRTASCategory="" jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.phaser" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + + + diff -r e32fe563e124 -r 04e171d2a747 effects/pingpongdelay/Source/PluginProcessor.cpp --- a/effects/pingpongdelay/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/pingpongdelay/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -261,12 +261,12 @@ // channelDataL and channelDataR are arrays of length numSamples which contain // the audio for one channel - float *channelDataL = buffer.getSampleData(0); - float *channelDataR = buffer.getSampleData(1); + float *channelDataL = buffer.getWritePointer(0); + float *channelDataR = buffer.getWritePointer(1); // delayDataL and delayDataR are the circular buffers for implementing delay - float* delayDataL = delayBuffer_.getSampleData(0); - float* delayDataR = delayBuffer_.getSampleData(1); + float* delayDataL = delayBuffer_.getWritePointer(0); + float* delayDataR = delayBuffer_.getWritePointer(1); for (int i = 0; i < numSamples; ++i) { diff -r e32fe563e124 -r 04e171d2a747 effects/pingpongdelay/pingpongdelay.jucer --- a/effects/pingpongdelay/pingpongdelay.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/pingpongdelay/pingpongdelay.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -8,11 +8,12 @@ pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="0" pluginTailLength="2" pluginEditorRequiresKeys="0" pluginAUExportPrefix="pingpongdelayAU" pluginAUViewClass="pingpongdelayAU_V1" pluginRTASCategory="" - jucerVersion="3.1.0" companyName="Reiss and McPherson" buildVST3="0" + jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.pingpongdelay" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + @@ -63,4 +64,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/pvoc_passthrough/Source/PluginEditor.cpp --- a/effects/pvoc_passthrough/Source/PluginEditor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/pvoc_passthrough/Source/PluginEditor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -125,9 +125,9 @@ { PVOCPassthroughAudioProcessor* ourProcessor = getProcessor(); - fftSizeComboBox_.setSelectedId(ourProcessor->fftSelectedSize_, false); - hopSizeComboBox_.setSelectedId(ourProcessor->hopSelectedSize_, false); - windowTypeComboBox_.setSelectedId(ourProcessor->windowType_, false); + fftSizeComboBox_.setSelectedId(ourProcessor->fftSelectedSize_, dontSendNotification); + hopSizeComboBox_.setSelectedId(ourProcessor->hopSelectedSize_, dontSendNotification); + windowTypeComboBox_.setSelectedId(ourProcessor->windowType_, dontSendNotification); } // This is our Slider::Listener callback, when the user drags a slider. diff -r e32fe563e124 -r 04e171d2a747 effects/pvoc_passthrough/Source/PluginProcessor.cpp --- a/effects/pvoc_passthrough/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/pvoc_passthrough/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -276,11 +276,11 @@ for (channel = 0; channel < numInputChannels; ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); // inputBufferData is the circular buffer for collecting input samples for the FFT - float* inputBufferData = inputBuffer_.getSampleData(jmin (channel, inputBuffer_.getNumChannels() - 1)); - float* outputBufferData = outputBuffer_.getSampleData(jmin (channel, inputBuffer_.getNumChannels() - 1)); + float* inputBufferData = inputBuffer_.getWritePointer(jmin (channel, inputBuffer_.getNumChannels() - 1)); + float* outputBufferData = outputBuffer_.getWritePointer(jmin (channel, inputBuffer_.getNumChannels() - 1)); // State variables need to be temporarily cached for each channel. We don't want the // operations on one channel to affect the identical behaviour of the next channel diff -r e32fe563e124 -r 04e171d2a747 effects/pvoc_passthrough/pvoc_passthrough.jucer --- a/effects/pvoc_passthrough/pvoc_passthrough.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/pvoc_passthrough/pvoc_passthrough.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -8,12 +8,12 @@ pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="pvoc_passthroughAU" pluginAUViewClass="pvoc_passthroughAU_V1" - pluginRTASCategory="" jucerVersion="3.1.0" companyName="Reiss and McPherson" + pluginRTASCategory="" jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.pvoc_passthrough" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + + + + diff -r e32fe563e124 -r 04e171d2a747 effects/pvoc_pitchshift/Source/PluginEditor.cpp --- a/effects/pvoc_pitchshift/Source/PluginEditor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/pvoc_pitchshift/Source/PluginEditor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -148,10 +148,10 @@ { PVOCPitchShiftAudioProcessor* ourProcessor = getProcessor(); - fftSizeComboBox_.setSelectedId(ourProcessor->fftSelectedSize_, false); - hopSizeComboBox_.setSelectedId(ourProcessor->hopSelectedSize_, false); - windowTypeComboBox_.setSelectedId(ourProcessor->windowType_, false); - pitchShiftComboBox_.setSelectedId(ourProcessor->pitchSelectedShift_, false); // (⊙_⊙) + fftSizeComboBox_.setSelectedId(ourProcessor->fftSelectedSize_, dontSendNotification); + hopSizeComboBox_.setSelectedId(ourProcessor->hopSelectedSize_, dontSendNotification); + windowTypeComboBox_.setSelectedId(ourProcessor->windowType_, dontSendNotification); + pitchShiftComboBox_.setSelectedId(ourProcessor->pitchSelectedShift_, dontSendNotification); // (⊙_⊙) } // This is our Slider::Listener callback, when the user drags a slider. diff -r e32fe563e124 -r 04e171d2a747 effects/pvoc_pitchshift/Source/PluginProcessor.cpp --- a/effects/pvoc_pitchshift/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/pvoc_pitchshift/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -354,11 +354,11 @@ // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); // inputBufferData is the circular buffer for collecting input samples for the FFT - float* inputBufferData = inputBuffer_.getSampleData(jmin (channel, inputBuffer_.getNumChannels() - 1)); - float* outputBufferData = outputBuffer_.getSampleData(jmin (channel, inputBuffer_.getNumChannels() - 1)); + float* inputBufferData = inputBuffer_.getWritePointer(jmin (channel, inputBuffer_.getNumChannels() - 1)); + float* outputBufferData = outputBuffer_.getWritePointer(jmin (channel, inputBuffer_.getNumChannels() - 1)); // State variables need to be temporarily cached for each channel. We don't want the // operations on one channel to affect the identical behaviour of the next channel diff -r e32fe563e124 -r 04e171d2a747 effects/pvoc_pitchshift/pvoc_pitchshift.jucer --- a/effects/pvoc_pitchshift/pvoc_pitchshift.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/pvoc_pitchshift/pvoc_pitchshift.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -8,11 +8,11 @@ pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="pvoc_pitchshiftAU" pluginAUViewClass="pvoc_passthroughAU_V1" pluginRTASCategory="" - jucerVersion="3.1.0" companyName="Reiss and McPherson" buildVST3="0" + jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="uk.ac.qmul.eecs.pvocpitchshift" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + + + diff -r e32fe563e124 -r 04e171d2a747 effects/reverb/reverb.jucer --- a/effects/reverb/reverb.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/reverb/reverb.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -8,10 +8,10 @@ pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="reverbAU" pluginAUViewClass="MasterCompressorAU_V1" pluginRTASCategory="" - jucerVersion="3.1.0" aaxIdentifier="uk.ac.qmul.eecs.reverb" pluginAAXCategory="" + jucerVersion="4.0.2" aaxIdentifier="uk.ac.qmul.eecs.reverb" pluginAAXCategory="" includeBinaryInAppConfig="1" buildVST3="0" buildAAX="0" companyName="Brecht De Man"> - + @@ -61,4 +61,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/ringmod/Source/PluginEditor.cpp --- a/effects/ringmod/Source/PluginEditor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/ringmod/Source/PluginEditor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -119,7 +119,7 @@ carrierFrequencySlider_.setValue(ourProcessor->carrierFrequency_, dontSendNotification); sweepWidthSlider_.setValue(ourProcessor->sweepWidth_, dontSendNotification); lfoFrequencySlider_.setValue(ourProcessor->lfoFrequency_, dontSendNotification); - waveformComboBox_.setSelectedId(ourProcessor->waveform_, false); + waveformComboBox_.setSelectedId(ourProcessor->waveform_, dontSendNotification); } // This is our Slider::Listener callback, when the user drags a slider. diff -r e32fe563e124 -r 04e171d2a747 effects/ringmod/Source/PluginProcessor.cpp --- a/effects/ringmod/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/ringmod/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -239,7 +239,7 @@ for (channel = 0; channel < numInputChannels; ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); // Make a temporary copy of any state variables declared in PluginProcessor.h which need to be // maintained between calls to processBlock(). Each channel needs to be processed identically diff -r e32fe563e124 -r 04e171d2a747 effects/ringmod/ringmod.jucer --- a/effects/ringmod/ringmod.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/ringmod/ringmod.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -7,12 +7,13 @@ pluginCode="ring" pluginChannelConfigs="{1, 1}, {2, 2}" pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="ringmodAU" - pluginAUViewClass="ringmodAU_V1" pluginRTASCategory="" jucerVersion="3.1.0" + pluginAUViewClass="ringmodAU_V1" pluginRTASCategory="" jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.ringmod" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + @@ -63,4 +64,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/robotisation/robotisation.jucer --- a/effects/robotisation/robotisation.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/robotisation/robotisation.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -8,11 +8,11 @@ pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="robotisationAU" pluginAUViewClass="pvoc_passthroughAU_V1" pluginRTASCategory="" - jucerVersion="3.1.0" companyName="Reiss and McPherson" aaxIdentifier="com.yourcompany.pvoc_passthrough" + jucerVersion="4.0.2" companyName="Reiss and McPherson" aaxIdentifier="com.yourcompany.pvoc_passthrough" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" buildVST3="0" buildAAX="0" includeBinaryInAppConfig="1"> - + + + diff -r e32fe563e124 -r 04e171d2a747 effects/tremolo/Source/PluginProcessor.cpp --- a/effects/tremolo/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/tremolo/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -231,7 +231,7 @@ for (channel = 0; channel < numInputChannels; ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); // Make a temporary copy of any state variables declared in PluginProcessor.h which need to be // maintained between calls to processBlock(). Each channel needs to be processed identically diff -r e32fe563e124 -r 04e171d2a747 effects/tremolo/tremolo.jucer --- a/effects/tremolo/tremolo.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/tremolo/tremolo.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -7,12 +7,13 @@ pluginCode="Plug" pluginChannelConfigs="{2,2},{1,1}" pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="tremoloAU" - pluginAUViewClass="tremoloAU_V1" pluginRTASCategory="" jucerVersion="3.1.0" + pluginAUViewClass="tremoloAU_V1" pluginRTASCategory="" jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.tremolo" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + @@ -63,4 +64,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/vibrato/Source/PluginEditor.cpp --- a/effects/vibrato/Source/PluginEditor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/vibrato/Source/PluginEditor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -136,8 +136,8 @@ sweepWidthSlider_.setValue(ourProcessor->sweepWidth_, dontSendNotification); frequencySlider_.setValue(ourProcessor->frequency_, dontSendNotification); - waveformComboBox_.setSelectedId(ourProcessor->waveform_, false); - interpolationComboBox_.setSelectedId(ourProcessor->interpolation_, false); + waveformComboBox_.setSelectedId(ourProcessor->waveform_, dontSendNotification); + interpolationComboBox_.setSelectedId(ourProcessor->interpolation_, dontSendNotification); // Update the pitch shift label only when something changes to avoid // needless calculations diff -r e32fe563e124 -r 04e171d2a747 effects/vibrato/Source/PluginProcessor.cpp --- a/effects/vibrato/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/vibrato/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -249,10 +249,10 @@ for (channel = 0; channel < numInputChannels; ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); // delayData is the circular buffer for implementing delay on this channel - float* delayData = delayBuffer_.getSampleData (jmin (channel, delayBuffer_.getNumChannels() - 1)); + float* delayData = delayBuffer_.getWritePointer (jmin (channel, delayBuffer_.getNumChannels() - 1)); // Make a temporary copy of any state variables declared in PluginProcessor.h which need to be // maintained between calls to processBlock(). Each channel needs to be processed identically diff -r e32fe563e124 -r 04e171d2a747 effects/vibrato/vibrato.jucer --- a/effects/vibrato/vibrato.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/vibrato/vibrato.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -7,12 +7,13 @@ pluginCode="vibr" pluginChannelConfigs="{2, 2}, {1, 1}" pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="vibratoAU" - pluginAUViewClass="vibratoAU_V1" pluginRTASCategory="" jucerVersion="3.1.0" + pluginAUViewClass="vibratoAU_V1" pluginRTASCategory="" jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.vibrato" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + @@ -63,4 +64,7 @@ + + + diff -r e32fe563e124 -r 04e171d2a747 effects/wahwah/Source/PluginProcessor.cpp --- a/effects/wahwah/Source/PluginProcessor.cpp Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/wahwah/Source/PluginProcessor.cpp Sun Nov 22 15:23:40 2015 +0000 @@ -239,7 +239,7 @@ for (channel = 0; channel < jmin(numInputChannels, numWahFilters_); ++channel) { // channelData is an array of length numSamples which contains the audio for one channel - float* channelData = buffer.getSampleData(channel); + float* channelData = buffer.getWritePointer(channel); // Run the samples through the IIR filter whose coefficients define the parametric // equaliser. See juce_IIRFilter.cpp for the implementation. diff -r e32fe563e124 -r 04e171d2a747 effects/wahwah/wahwah.jucer --- a/effects/wahwah/wahwah.jucer Fri Oct 10 15:41:23 2014 +0100 +++ b/effects/wahwah/wahwah.jucer Sun Nov 22 15:23:40 2015 +0000 @@ -7,12 +7,13 @@ pluginCode="wawa" pluginChannelConfigs="{1, 1}, {2, 2}" pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="wahwahAU" - pluginAUViewClass="wahwahAU_V1" pluginRTASCategory="" jucerVersion="3.1.0" + pluginAUViewClass="wahwahAU_V1" pluginRTASCategory="" jucerVersion="4.0.2" companyName="Reiss and McPherson" buildVST3="0" buildAAX="0" aaxIdentifier="com.yourcompany.wahwah" pluginAAXCategory="AAX_ePlugInCategory_Dynamics" includeBinaryInAppConfig="1"> - + @@ -67,4 +68,7 @@ + + +