| @@ -0,0 +1,27 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist> | |||
| <dict> | |||
| <key>CFBundleExecutable</key> | |||
| <string>${EXECUTABLE_NAME}</string> | |||
| <key>CFBundleIconFile</key> | |||
| <string></string> | |||
| <key>CFBundleIdentifier</key> | |||
| <string>com.yourcompany.SimpleFFTExample</string> | |||
| <key>CFBundleName</key> | |||
| <string>SimpleFFTExample</string> | |||
| <key>CFBundlePackageType</key> | |||
| <string>APPL</string> | |||
| <key>CFBundleSignature</key> | |||
| <string>????</string> | |||
| <key>CFBundleShortVersionString</key> | |||
| <string>1.0.0</string> | |||
| <key>CFBundleVersion</key> | |||
| <string>1.0.0</string> | |||
| <key>NSHumanReadableCopyright</key> | |||
| <string></string> | |||
| <key>NSHighResolutionCapable</key> | |||
| <true/> | |||
| </dict> | |||
| </plist> | |||
| @@ -0,0 +1,19 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 11.00 | |||
| # Visual Studio 2013 | |||
| Project("{E2F0E2D2-88FF-EF53-E779-C571B75BEB02}") = "SimpleFFTExample", "SimpleFFTExample.vcxproj", "{D3EA4D64-39DA-D13A-AC10-C306C86BA9F5}" | |||
| EndProject | |||
| Global | |||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
| Debug|Win32 = Debug|Win32 | |||
| Release|Win32 = Release|Win32 | |||
| EndGlobalSection | |||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||
| {D3EA4D64-39DA-D13A-AC10-C306C86BA9F5}.Debug|Win32.ActiveCfg = Debug|Win32 | |||
| {D3EA4D64-39DA-D13A-AC10-C306C86BA9F5}.Debug|Win32.Build.0 = Debug|Win32 | |||
| {D3EA4D64-39DA-D13A-AC10-C306C86BA9F5}.Release|Win32.ActiveCfg = Release|Win32 | |||
| {D3EA4D64-39DA-D13A-AC10-C306C86BA9F5}.Release|Win32.Build.0 = Release|Win32 | |||
| EndGlobalSection | |||
| GlobalSection(SolutionProperties) = preSolution | |||
| HideSolutionNode = FALSE | |||
| EndGlobalSection | |||
| EndGlobal | |||
| @@ -0,0 +1,29 @@ | |||
| #ifdef JUCE_USER_DEFINED_RC_FILE | |||
| #include JUCE_USER_DEFINED_RC_FILE | |||
| #else | |||
| #undef WIN32_LEAN_AND_MEAN | |||
| #define WIN32_LEAN_AND_MEAN | |||
| #include <windows.h> | |||
| VS_VERSION_INFO VERSIONINFO | |||
| FILEVERSION 1,0,0,0 | |||
| BEGIN | |||
| BLOCK "StringFileInfo" | |||
| BEGIN | |||
| BLOCK "040904E4" | |||
| BEGIN | |||
| VALUE "FileDescription", "SimpleFFTExample\0" | |||
| VALUE "FileVersion", "1.0.0\0" | |||
| VALUE "ProductName", "SimpleFFTExample\0" | |||
| VALUE "ProductVersion", "1.0.0\0" | |||
| END | |||
| END | |||
| BLOCK "VarFileInfo" | |||
| BEGIN | |||
| VALUE "Translation", 0x409, 65001 | |||
| END | |||
| END | |||
| #endif | |||
| @@ -0,0 +1,179 @@ | |||
| /* | |||
| IMPORTANT! This file is auto-generated each time you save your | |||
| project - if you alter its contents, your changes may be overwritten! | |||
| There's a section below where you can add your own custom code safely, and the | |||
| Introjucer will preserve the contents of that block, but the best way to change | |||
| any of these definitions is by using the Introjucer's project settings. | |||
| Any commented-out settings will assume their default values. | |||
| */ | |||
| #ifndef __JUCE_APPCONFIG_CGCXPD__ | |||
| #define __JUCE_APPCONFIG_CGCXPD__ | |||
| //============================================================================== | |||
| // [BEGIN_USER_CODE_SECTION] | |||
| // (You can add your own code in this section, and the Introjucer will not overwrite it) | |||
| // [END_USER_CODE_SECTION] | |||
| //============================================================================== | |||
| #define JUCE_MODULE_AVAILABLE_juce_audio_basics 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_audio_devices 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_audio_formats 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_audio_processors 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_audio_utils 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_core 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_data_structures 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_events 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_graphics 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_gui_basics 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_gui_extra 1 | |||
| //============================================================================== | |||
| // juce_audio_devices flags: | |||
| #ifndef JUCE_ASIO | |||
| //#define JUCE_ASIO | |||
| #endif | |||
| #ifndef JUCE_WASAPI | |||
| //#define JUCE_WASAPI | |||
| #endif | |||
| #ifndef JUCE_WASAPI_EXCLUSIVE | |||
| //#define JUCE_WASAPI_EXCLUSIVE | |||
| #endif | |||
| #ifndef JUCE_DIRECTSOUND | |||
| //#define JUCE_DIRECTSOUND | |||
| #endif | |||
| #ifndef JUCE_ALSA | |||
| //#define JUCE_ALSA | |||
| #endif | |||
| #ifndef JUCE_JACK | |||
| //#define JUCE_JACK | |||
| #endif | |||
| #ifndef JUCE_USE_ANDROID_OPENSLES | |||
| //#define JUCE_USE_ANDROID_OPENSLES | |||
| #endif | |||
| #ifndef JUCE_USE_CDREADER | |||
| //#define JUCE_USE_CDREADER | |||
| #endif | |||
| #ifndef JUCE_USE_CDBURNER | |||
| //#define JUCE_USE_CDBURNER | |||
| #endif | |||
| //============================================================================== | |||
| // juce_audio_formats flags: | |||
| #ifndef JUCE_USE_FLAC | |||
| //#define JUCE_USE_FLAC | |||
| #endif | |||
| #ifndef JUCE_USE_OGGVORBIS | |||
| //#define JUCE_USE_OGGVORBIS | |||
| #endif | |||
| #ifndef JUCE_USE_MP3AUDIOFORMAT | |||
| //#define JUCE_USE_MP3AUDIOFORMAT | |||
| #endif | |||
| #ifndef JUCE_USE_LAME_AUDIO_FORMAT | |||
| //#define JUCE_USE_LAME_AUDIO_FORMAT | |||
| #endif | |||
| #ifndef JUCE_USE_WINDOWS_MEDIA_FORMAT | |||
| //#define JUCE_USE_WINDOWS_MEDIA_FORMAT | |||
| #endif | |||
| //============================================================================== | |||
| // juce_audio_processors flags: | |||
| #ifndef JUCE_PLUGINHOST_VST | |||
| //#define JUCE_PLUGINHOST_VST | |||
| #endif | |||
| #ifndef JUCE_PLUGINHOST_VST3 | |||
| //#define JUCE_PLUGINHOST_VST3 | |||
| #endif | |||
| #ifndef JUCE_PLUGINHOST_AU | |||
| //#define JUCE_PLUGINHOST_AU | |||
| #endif | |||
| //============================================================================== | |||
| // juce_core flags: | |||
| #ifndef JUCE_FORCE_DEBUG | |||
| //#define JUCE_FORCE_DEBUG | |||
| #endif | |||
| #ifndef JUCE_LOG_ASSERTIONS | |||
| //#define JUCE_LOG_ASSERTIONS | |||
| #endif | |||
| #ifndef JUCE_CHECK_MEMORY_LEAKS | |||
| //#define JUCE_CHECK_MEMORY_LEAKS | |||
| #endif | |||
| #ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES | |||
| //#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES | |||
| #endif | |||
| #ifndef JUCE_INCLUDE_ZLIB_CODE | |||
| //#define JUCE_INCLUDE_ZLIB_CODE | |||
| #endif | |||
| //============================================================================== | |||
| // juce_graphics flags: | |||
| #ifndef JUCE_USE_COREIMAGE_LOADER | |||
| //#define JUCE_USE_COREIMAGE_LOADER | |||
| #endif | |||
| #ifndef JUCE_USE_DIRECTWRITE | |||
| //#define JUCE_USE_DIRECTWRITE | |||
| #endif | |||
| //============================================================================== | |||
| // juce_gui_basics flags: | |||
| #ifndef JUCE_ENABLE_REPAINT_DEBUGGING | |||
| //#define JUCE_ENABLE_REPAINT_DEBUGGING | |||
| #endif | |||
| #ifndef JUCE_USE_XSHM | |||
| //#define JUCE_USE_XSHM | |||
| #endif | |||
| #ifndef JUCE_USE_XRENDER | |||
| //#define JUCE_USE_XRENDER | |||
| #endif | |||
| #ifndef JUCE_USE_XCURSOR | |||
| //#define JUCE_USE_XCURSOR | |||
| #endif | |||
| //============================================================================== | |||
| // juce_gui_extra flags: | |||
| #ifndef JUCE_WEB_BROWSER | |||
| //#define JUCE_WEB_BROWSER | |||
| #endif | |||
| #ifndef JUCE_ENABLE_LIVE_CONSTANT_EDITOR | |||
| //#define JUCE_ENABLE_LIVE_CONSTANT_EDITOR | |||
| #endif | |||
| #endif // __JUCE_APPCONFIG_CGCXPD__ | |||
| @@ -0,0 +1,44 @@ | |||
| /* | |||
| IMPORTANT! This file is auto-generated each time you save your | |||
| project - if you alter its contents, your changes may be overwritten! | |||
| This is the header file that your files should include in order to get all the | |||
| JUCE library headers. You should avoid including the JUCE headers directly in | |||
| your own source files, because that wouldn't pick up the correct configuration | |||
| options for your app. | |||
| */ | |||
| #ifndef __APPHEADERFILE_CGCXPD__ | |||
| #define __APPHEADERFILE_CGCXPD__ | |||
| #include "AppConfig.h" | |||
| #include "modules/juce_audio_basics/juce_audio_basics.h" | |||
| #include "modules/juce_audio_devices/juce_audio_devices.h" | |||
| #include "modules/juce_audio_formats/juce_audio_formats.h" | |||
| #include "modules/juce_audio_processors/juce_audio_processors.h" | |||
| #include "modules/juce_audio_utils/juce_audio_utils.h" | |||
| #include "modules/juce_core/juce_core.h" | |||
| #include "modules/juce_data_structures/juce_data_structures.h" | |||
| #include "modules/juce_events/juce_events.h" | |||
| #include "modules/juce_graphics/juce_graphics.h" | |||
| #include "modules/juce_gui_basics/juce_gui_basics.h" | |||
| #include "modules/juce_gui_extra/juce_gui_extra.h" | |||
| #if ! DONT_SET_USING_JUCE_NAMESPACE | |||
| // If your code uses a lot of JUCE classes, then this will obviously save you | |||
| // a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE. | |||
| using namespace juce; | |||
| #endif | |||
| #if ! JUCE_DONT_DECLARE_PROJECTINFO | |||
| namespace ProjectInfo | |||
| { | |||
| const char* const projectName = "SimpleFFTExample"; | |||
| const char* const versionString = "1.0.0"; | |||
| const int versionNumber = 0x10000; | |||
| } | |||
| #endif | |||
| #endif // __APPHEADERFILE_CGCXPD__ | |||
| @@ -0,0 +1,12 @@ | |||
| Important Note!! | |||
| ================ | |||
| The purpose of this folder is to contain files that are auto-generated by the Introjucer, | |||
| and ALL files in this folder will be mercilessly DELETED and completely re-written whenever | |||
| the Introjucer saves your project. | |||
| Therefore, it's a bad idea to make any manual changes to the files in here, or to | |||
| put any of your own files in here if you don't want to lose them. (Of course you may choose | |||
| to add the folder's contents to your version-control system so that you can re-merge your own | |||
| modifications after the Introjucer has saved its changes). | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_audio_basics/juce_audio_basics.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_audio_devices/juce_audio_devices.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_audio_formats/juce_audio_formats.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_audio_processors/juce_audio_processors.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_audio_utils/juce_audio_utils.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_core/juce_core.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_data_structures/juce_data_structures.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_events/juce_events.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_graphics/juce_graphics.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_gui_basics/juce_gui_basics.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_gui_extra/juce_gui_extra.h" | |||
| @@ -0,0 +1,71 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <JUCERPROJECT id="cgcxPd" name="SimpleFFTExample" projectType="guiapp" version="1.0.0" | |||
| bundleIdentifier="com.yourcompany.SimpleFFTExample" includeBinaryInAppConfig="1" | |||
| jucerVersion="3.1.1"> | |||
| <MAINGROUP id="rZCHr8" name="SimpleFFTExample"> | |||
| <GROUP id="{8DC23B3F-98AC-AB1C-B26A-E693AF2DF0D2}" name="Source"> | |||
| <FILE id="B1L62H" name="SpectrogramComponent.h" compile="0" resource="0" | |||
| file="Source/SpectrogramComponent.h"/> | |||
| <FILE id="uviznd" name="Main.cpp" compile="1" resource="0" file="Source/Main.cpp"/> | |||
| </GROUP> | |||
| </MAINGROUP> | |||
| <EXPORTFORMATS> | |||
| <XCODE_MAC targetFolder="Builds/MacOSX"> | |||
| <CONFIGURATIONS> | |||
| <CONFIGURATION name="Debug" osxSDK="default" osxCompatibility="default" osxArchitecture="default" | |||
| isDebug="1" optimisation="1" targetName="SimpleFFTExample"/> | |||
| <CONFIGURATION name="Release" osxSDK="default" osxCompatibility="default" osxArchitecture="default" | |||
| isDebug="0" optimisation="3" targetName="SimpleFFTExample"/> | |||
| </CONFIGURATIONS> | |||
| <MODULEPATHS> | |||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_extra" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_devices" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_formats" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_processors" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_utils" path="../../modules"/> | |||
| </MODULEPATHS> | |||
| </XCODE_MAC> | |||
| <VS2013 targetFolder="Builds/VisualStudio2013"> | |||
| <CONFIGURATIONS> | |||
| <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit" | |||
| isDebug="1" optimisation="1" targetName="SimpleFFTExample"/> | |||
| <CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit" | |||
| isDebug="0" optimisation="3" targetName="SimpleFFTExample"/> | |||
| </CONFIGURATIONS> | |||
| <MODULEPATHS> | |||
| <MODULEPATH id="juce_gui_extra" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_utils" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_processors" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_formats" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_devices" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_basics" path="../../modules"/> | |||
| </MODULEPATHS> | |||
| </VS2013> | |||
| </EXPORTFORMATS> | |||
| <MODULES> | |||
| <MODULES id="juce_audio_basics" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULES id="juce_audio_devices" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULES id="juce_audio_formats" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULES id="juce_audio_processors" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULES id="juce_audio_utils" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULES id="juce_core" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULES id="juce_data_structures" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULES id="juce_events" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULES id="juce_graphics" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULES id="juce_gui_basics" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULES id="juce_gui_extra" showAllCode="1" useLocalCopy="0"/> | |||
| </MODULES> | |||
| <JUCEOPTIONS/> | |||
| </JUCERPROJECT> | |||
| @@ -0,0 +1,80 @@ | |||
| /* | |||
| ============================================================================== | |||
| JUCE demo code - use at your own risk! | |||
| ============================================================================== | |||
| */ | |||
| #include "../JuceLibraryCode/JuceHeader.h" | |||
| #include "SpectrogramComponent.h" | |||
| //============================================================================== | |||
| class SimpleFFTExampleApplication : public JUCEApplication | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| SimpleFFTExampleApplication() {} | |||
| const String getApplicationName() override { return ProjectInfo::projectName; } | |||
| const String getApplicationVersion() override { return ProjectInfo::versionString; } | |||
| bool moreThanOneInstanceAllowed() override { return true; } | |||
| //============================================================================== | |||
| void initialise (const String& /*commandLine*/) override | |||
| { | |||
| mainWindow = new MainWindow(); | |||
| } | |||
| void shutdown() override | |||
| { | |||
| mainWindow = nullptr; // (deletes our window) | |||
| } | |||
| //============================================================================== | |||
| void systemRequestedQuit() override | |||
| { | |||
| // This is called when the app is being asked to quit: you can ignore this | |||
| // request and let the app carry on running, or call quit() to allow the app to close. | |||
| quit(); | |||
| } | |||
| //============================================================================== | |||
| /* | |||
| This class implements the desktop window that contains an instance of | |||
| our MainContentComponent class. | |||
| */ | |||
| class MainWindow : public DocumentWindow | |||
| { | |||
| public: | |||
| MainWindow() : DocumentWindow (ProjectInfo::projectName, | |||
| Colours::lightgrey, | |||
| DocumentWindow::allButtons) | |||
| { | |||
| setUsingNativeTitleBar (true); | |||
| setContentOwned (new SpectrogramComponent(), true); | |||
| setResizable (true, true); | |||
| centreWithSize (getWidth(), getHeight()); | |||
| setVisible (true); | |||
| } | |||
| void closeButtonPressed() override | |||
| { | |||
| // This is called when the user tries to close this window. Here, we'll just | |||
| // ask the app to quit when this happens, but you can change this to do | |||
| // whatever you need. | |||
| JUCEApplication::getInstance()->systemRequestedQuit(); | |||
| } | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow) | |||
| }; | |||
| private: | |||
| ScopedPointer<MainWindow> mainWindow; | |||
| }; | |||
| //============================================================================== | |||
| // This macro generates the main() routine that launches the app. | |||
| START_JUCE_APPLICATION (SimpleFFTExampleApplication) | |||
| @@ -0,0 +1,132 @@ | |||
| /* | |||
| ============================================================================== | |||
| JUCE demo code - use at your own risk! | |||
| ============================================================================== | |||
| */ | |||
| class SpectrogramComponent : public AudioAppComponent, | |||
| private Timer | |||
| { | |||
| public: | |||
| SpectrogramComponent() | |||
| : forwardFFT (fftOrder, false), | |||
| spectrogramImage (Image::RGB, 512, 512, true), | |||
| fifoIndex (0), | |||
| nextFFTBlockReady (false) | |||
| { | |||
| setOpaque (true); | |||
| setAudioChannels (2, 0); // we want a couple of input channels but no outputs | |||
| startTimerHz (60); | |||
| setSize (700, 500); | |||
| } | |||
| ~SpectrogramComponent() | |||
| { | |||
| shutdownAudio(); | |||
| } | |||
| //======================================================================= | |||
| void prepareToPlay (int /*samplesPerBlockExpected*/, double /*newSampleRate*/) override | |||
| { | |||
| // (nothing to do here) | |||
| } | |||
| void releaseResources() override | |||
| { | |||
| // (nothing to do here) | |||
| } | |||
| void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override | |||
| { | |||
| if (bufferToFill.buffer->getNumChannels() > 0) | |||
| { | |||
| const float* channelData = bufferToFill.buffer->getWritePointer (0, bufferToFill.startSample); | |||
| for (int i = 0; i < bufferToFill.numSamples; ++i) | |||
| pushNextSampleIntoFifo (channelData[i]); | |||
| } | |||
| } | |||
| //======================================================================= | |||
| void paint (Graphics& g) override | |||
| { | |||
| g.fillAll (Colours::black); | |||
| g.setOpacity (1.0f); | |||
| g.drawImageWithin (spectrogramImage, 0, 0, getWidth(), getHeight(), RectanglePlacement::stretchToFit); | |||
| } | |||
| void timerCallback() override | |||
| { | |||
| if (nextFFTBlockReady) | |||
| { | |||
| drawNextLineOfSpectrogram(); | |||
| nextFFTBlockReady = false; | |||
| repaint(); | |||
| } | |||
| } | |||
| void pushNextSampleIntoFifo (float sample) noexcept | |||
| { | |||
| // if the fifo contains enough data, set a flag to say | |||
| // that the next line should now be rendered.. | |||
| if (fifoIndex == fftSize) | |||
| { | |||
| if (! nextFFTBlockReady) | |||
| { | |||
| zeromem (fftData, sizeof (fftData)); | |||
| memcpy (fftData, fifo, sizeof (fifo)); | |||
| nextFFTBlockReady = true; | |||
| } | |||
| fifoIndex = 0; | |||
| } | |||
| fifo[fifoIndex++] = sample; | |||
| } | |||
| void drawNextLineOfSpectrogram() | |||
| { | |||
| const int rightHandEdge = spectrogramImage.getWidth() - 1; | |||
| const int imageHeight = spectrogramImage.getHeight(); | |||
| // first, shuffle our image leftwards by 1 pixel.. | |||
| spectrogramImage.moveImageSection (0, 0, 1, 0, rightHandEdge, imageHeight); | |||
| // then render our FFT data.. | |||
| forwardFFT.performFrequencyOnlyForwardTransform (fftData); | |||
| // find the range of values produced, so we can scale our rendering to | |||
| // show up the detail clearly | |||
| Range<float> maxLevel = FloatVectorOperations::findMinAndMax (fftData, fftSize / 2); | |||
| for (int y = 0; y < imageHeight; ++y) | |||
| { | |||
| const float skewedProportionY = 1.0f - std::exp (std::log (y / (float) imageHeight) * 0.2f); | |||
| const int fftDataIndex = jlimit (0, fftSize / 2, (int) (skewedProportionY * fftSize / 2)); | |||
| const float level = jmap (fftData[fftDataIndex], 0.0f, maxLevel.getEnd(), 0.0f, 1.0f); | |||
| spectrogramImage.setPixelAt (rightHandEdge, y, Colour::fromHSV (level, 1.0f, level, 1.0f)); | |||
| } | |||
| } | |||
| enum | |||
| { | |||
| fftOrder = 10, | |||
| fftSize = 1 << fftOrder | |||
| }; | |||
| private: | |||
| FFT forwardFFT; | |||
| Image spectrogramImage; | |||
| float fifo [fftSize]; | |||
| float fftData [2 * fftSize]; | |||
| int fifoIndex; | |||
| bool nextFFTBlockReady; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SpectrogramComponent) | |||
| }; | |||