Browse Source

Added a plucked-string synthesiser demo app.

tags/2021-05-28
jules 10 years ago
parent
commit
4bf5e235ba
26 changed files with 7283 additions and 0 deletions
  1. +27
    -0
      examples/PluckedStringsDemo/Builds/MacOSX/Info.plist
  2. +1998
    -0
      examples/PluckedStringsDemo/Builds/MacOSX/PluckedStringsDemo.xcodeproj/project.pbxproj
  3. BIN
      examples/PluckedStringsDemo/Builds/MacOSX/RecentFilesMenuTemplate.nib
  4. +19
    -0
      examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo.sln
  5. +1642
    -0
      examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo.vcxproj
  6. +2750
    -0
      examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo.vcxproj.filters
  7. +29
    -0
      examples/PluckedStringsDemo/Builds/VisualStudio2013/resources.rc
  8. +179
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/AppConfig.h
  9. +44
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/JuceHeader.h
  10. +12
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/ReadMe.txt
  11. +5
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.h
  12. +5
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.h
  13. +5
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.h
  14. +5
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.h
  15. +5
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_audio_utils/juce_audio_utils.h
  16. +5
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_core/juce_core.h
  17. +5
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.h
  18. +5
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_events/juce_events.h
  19. +5
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_graphics/juce_graphics.h
  20. +5
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.h
  21. +5
    -0
      examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_gui_extra/juce_gui_extra.h
  22. +75
    -0
      examples/PluckedStringsDemo/PluckedStringsDemo.jucer
  23. +92
    -0
      examples/PluckedStringsDemo/Source/Main.cpp
  24. +88
    -0
      examples/PluckedStringsDemo/Source/StringComponent.h
  25. +148
    -0
      examples/PluckedStringsDemo/Source/StringDemoComponent.h
  26. +125
    -0
      examples/PluckedStringsDemo/Source/StringSynthesiser.h

+ 27
- 0
examples/PluckedStringsDemo/Builds/MacOSX/Info.plist View File

@@ -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.timurdoumler.PluckedStringsDemo</string>
<key>CFBundleName</key>
<string>PluckedStringsDemo</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>

+ 1998
- 0
examples/PluckedStringsDemo/Builds/MacOSX/PluckedStringsDemo.xcodeproj/project.pbxproj
File diff suppressed because it is too large
View File


BIN
examples/PluckedStringsDemo/Builds/MacOSX/RecentFilesMenuTemplate.nib View File


+ 19
- 0
examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo.sln View File

@@ -0,0 +1,19 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2013
Project("{798408B1-275B-0B42-1439-1A3AA75C50F3}") = "PluckedStringsDemo", "PluckedStringsDemo.vcxproj", "{A8C8CD6F-F9CA-737E-DC8B-DA724521F17B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A8C8CD6F-F9CA-737E-DC8B-DA724521F17B}.Debug|Win32.ActiveCfg = Debug|Win32
{A8C8CD6F-F9CA-737E-DC8B-DA724521F17B}.Debug|Win32.Build.0 = Debug|Win32
{A8C8CD6F-F9CA-737E-DC8B-DA724521F17B}.Release|Win32.ActiveCfg = Release|Win32
{A8C8CD6F-F9CA-737E-DC8B-DA724521F17B}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

+ 1642
- 0
examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo.vcxproj
File diff suppressed because it is too large
View File


+ 2750
- 0
examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo.vcxproj.filters
File diff suppressed because it is too large
View File


+ 29
- 0
examples/PluckedStringsDemo/Builds/VisualStudio2013/resources.rc View File

@@ -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", "PluckedStringsDemo\0"
VALUE "FileVersion", "1.0.0\0"
VALUE "ProductName", "PluckedStringsDemo\0"
VALUE "ProductVersion", "1.0.0\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 65001
END
END
#endif

+ 179
- 0
examples/PluckedStringsDemo/JuceLibraryCode/AppConfig.h View File

@@ -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_JKHEJM__
#define __JUCE_APPCONFIG_JKHEJM__
//==============================================================================
// [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_JKHEJM__

+ 44
- 0
examples/PluckedStringsDemo/JuceLibraryCode/JuceHeader.h View File

@@ -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_JKHEJM__
#define __APPHEADERFILE_JKHEJM__
#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 = "PluckedStringsDemo";
const char* const versionString = "1.0.0";
const int versionNumber = 0x10000;
}
#endif
#endif // __APPHEADERFILE_JKHEJM__

+ 12
- 0
examples/PluckedStringsDemo/JuceLibraryCode/ReadMe.txt View File

@@ -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).

+ 5
- 0
examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.h View File

@@ -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"

+ 5
- 0
examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.h View File

@@ -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"

+ 5
- 0
examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.h View File

@@ -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"

+ 5
- 0
examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.h View File

@@ -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"

+ 5
- 0
examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_audio_utils/juce_audio_utils.h View File

@@ -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"

+ 5
- 0
examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_core/juce_core.h View File

@@ -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"

+ 5
- 0
examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.h View File

@@ -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"

+ 5
- 0
examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_events/juce_events.h View File

@@ -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"

+ 5
- 0
examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_graphics/juce_graphics.h View File

@@ -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"

+ 5
- 0
examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.h View File

@@ -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"

+ 5
- 0
examples/PluckedStringsDemo/JuceLibraryCode/modules/juce_gui_extra/juce_gui_extra.h View File

@@ -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"

+ 75
- 0
examples/PluckedStringsDemo/PluckedStringsDemo.jucer View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<JUCERPROJECT id="jKHEJM" name="PluckedStringsDemo" projectType="guiapp" version="1.0.0"
bundleIdentifier="com.timurdoumler.PluckedStringsDemo" includeBinaryInAppConfig="1"
jucerVersion="3.1.1">
<MAINGROUP id="IWdVf7" name="PluckedStringsDemo">
<GROUP id="{8800CD50-6741-8B75-0305-FAF13427EF5D}" name="Source">
<FILE id="Z7hWe1" name="StringSynthesiser.h" compile="0" resource="0"
file="Source/StringSynthesiser.h"/>
<FILE id="UFFPPQ" name="StringComponent.h" compile="0" resource="0"
file="Source/StringComponent.h"/>
<FILE id="Sut3oJ" name="StringDemoComponent.h" compile="0" resource="0"
file="Source/StringDemoComponent.h"/>
<FILE id="Y5HoZY" 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="PluckedStringsDemo"/>
<CONFIGURATION name="Release" osxSDK="default" osxCompatibility="default" osxArchitecture="default"
isDebug="0" optimisation="2" targetName="PluckedStringsDemo"/>
</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="PluckedStringsDemo"/>
<CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit"
isDebug="0" optimisation="2" targetName="PluckedStringsDemo"/>
</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>

+ 92
- 0
examples/PluckedStringsDemo/Source/Main.cpp View File

@@ -0,0 +1,92 @@
/*
==============================================================================
JUCE demo code - use at your own risk!
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
#include "StringDemoComponent.h"
//==============================================================================
class PluckedStringsDemoApplication : public JUCEApplication
{
public:
//==============================================================================
PluckedStringsDemoApplication() {}
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();
}
void anotherInstanceStarted (const String& /*commandLine*/) override
{
// When another instance of the app is launched while this one is running,
// this method is invoked, and the commandLine parameter tells you what
// the other instance's command-line arguments were.
}
//==============================================================================
class MainWindow : public DocumentWindow
{
public:
MainWindow() : DocumentWindow (ProjectInfo::projectName,
Colours::lightgrey,
DocumentWindow::allButtons)
{
setUsingNativeTitleBar (true);
setContentOwned (new StringDemoComponent(), true);
setResizable (true, false);
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();
}
/* Note: Be careful if you override any DocumentWindow methods - the base
class uses a lot of them, so by overriding you might break its functionality.
It's best to do all your work in your content component instead, but if
you really have to override any DocumentWindow methods, make sure your
subclass also calls the superclass's method.
*/
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 (PluckedStringsDemoApplication)

+ 88
- 0
examples/PluckedStringsDemo/Source/StringComponent.h View File

@@ -0,0 +1,88 @@
/*
==============================================================================
JUCE demo code - use at your own risk!
==============================================================================
*/
/*
This component represents a horizontal vibrating musical string of fixed height
and variable length. The string can be excited by calling stringPlucked().
*/
class StringComponent : public Component,
private Timer
{
public:
StringComponent (int lengthInPixels, Colour stringColour)
: length (lengthInPixels), colour (stringColour)
{
// ignore mouse-clicks so that our parent can get them instead.
setInterceptsMouseClicks (false, false);
setSize (length, height);
startTimerHz (60);
}
//=======================================================================
void stringPlucked (float pluckPositionRelative)
{
amplitude = maxAmplitude * std::sin (pluckPositionRelative * float_Pi);
phase = float_Pi;
}
//=======================================================================
void paint (Graphics& g) override
{
g.setColour (colour);
g.strokePath (generateStringPath(), PathStrokeType (2.0f));
}
Path generateStringPath() const
{
const float y = height / 2.0f;
Path stringPath;
stringPath.startNewSubPath (0, y);
stringPath.quadraticTo (length / 2.0f, y + (std::sin (phase) * amplitude), (float) length, y);
return stringPath;
}
//==============================================================================
void timerCallback() override
{
updateAmplitude();
updatePhase();
repaint();
}
void updateAmplitude()
{
// this determines the decay of the visible string vibration.
amplitude *= 0.99f;
}
void updatePhase()
{
// this determines the visible vibration frequency.
// just an arbitrary number chosen to look OK:
const float phaseStep = 400.0f / length;
phase += phaseStep;
if (phase > float_Pi)
phase -= 2.0f * float_Pi;
}
private:
//=======================================================================
int length;
Colour colour;
int height = 20;
float amplitude = 0.0f;
const float maxAmplitude = 12.0f;
float phase = 0.0f;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StringComponent)
};

+ 148
- 0
examples/PluckedStringsDemo/Source/StringDemoComponent.h View File

@@ -0,0 +1,148 @@
/*
==============================================================================
JUCE demo code - use at your own risk!
==============================================================================
*/
#include "StringSynthesiser.h"
#include "StringComponent.h"
//==============================================================================
class StringDemoComponent : public AudioAppComponent
{
public:
StringDemoComponent()
{
createStringComponents();
setSize (800, 560);
// specify the number of input and output channels that we want to open
setAudioChannels (0, 2);
}
~StringDemoComponent()
{
shutdownAudio();
}
//=======================================================================
void prepareToPlay (int /*samplesPerBlockExpected*/, double sampleRate) override
{
generateStringSynths (sampleRate);
}
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
{
bufferToFill.clearActiveBufferRegion();
for (int channel = 0; channel < bufferToFill.buffer->getNumChannels(); ++channel)
{
float* const channelData = bufferToFill.buffer->getWritePointer (channel, bufferToFill.startSample);
if (channel == 0)
{
for (auto synth : stringSynths)
synth->generateAndAddData (channelData, bufferToFill.numSamples);
}
else
{
memcpy (channelData,
bufferToFill.buffer->getReadPointer (0),
bufferToFill.numSamples * sizeof (float));
}
}
}
void releaseResources() override
{
stringSynths.clear();
}
//=======================================================================
void paint (Graphics& g) override
{
g.fillAll (Colours::black);
}
void resized() override
{
int xPos = 20;
int yPos = 20;
int yDistance = 50;
for (auto stringLine : stringLines)
{
stringLine->setTopLeftPosition (xPos, yPos);
yPos += yDistance;
addAndMakeVisible (stringLine);
}
}
private:
void mouseDown (const MouseEvent& e) override
{
mouseDrag (e);
}
void mouseDrag (const MouseEvent& e) override
{
for (int i = 0; i < stringLines.size(); ++i)
{
auto* stringLine = stringLines.getUnchecked(i);
if (stringLine->getBounds().contains (e.getPosition()))
{
float position = (e.position.x - stringLine->getX()) / stringLine->getWidth();
stringLine->stringPlucked (position);
stringSynths.getUnchecked(i)->stringPlucked (position);
}
}
}
//=======================================================================
struct StringParameters
{
StringParameters (int midiNote)
: frequencyInHz (MidiMessage::getMidiNoteInHertz (midiNote)),
lengthInPixels ((int) (760 / (frequencyInHz / MidiMessage::getMidiNoteInHertz (42))))
{
}
double frequencyInHz;
int lengthInPixels;
};
static std::vector<StringParameters> getDefaultStringParameters()
{
return { 42, 44, 46, 49, 51, 54, 56, 58, 61, 63, 66, 68, 70 };
}
void createStringComponents()
{
for (auto stringParams : getDefaultStringParameters())
{
stringLines.add (new StringComponent (stringParams.lengthInPixels,
Colour::fromHSV (Random().nextFloat(), 0.6f, 0.9f, 1.0f)));
}
}
void generateStringSynths (double sampleRate)
{
stringSynths.clear();
for (auto stringParams : getDefaultStringParameters())
{
stringSynths.add (new StringSynthesiser (sampleRate, stringParams.frequencyInHz));
}
}
//=======================================================================
OwnedArray<StringComponent> stringLines;
OwnedArray<StringSynthesiser> stringSynths;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StringDemoComponent)
};

+ 125
- 0
examples/PluckedStringsDemo/Source/StringSynthesiser.h View File

@@ -0,0 +1,125 @@
/*
==============================================================================
JUCE demo code - use at your own risk!
==============================================================================
*/
/**
A very basic generator of a simulated plucked string sound, implementing
the Karplus-Strong algorithm.
Not performance-optimised!
*/
class StringSynthesiser
{
public:
//=======================================================================
/** Constructor.
@param sampleRate The audio sample rate to use.
@param frequencyInHz The fundamental frequency of the simulated string in
Hertz.
*/
StringSynthesiser (double sampleRate, double frequencyInHz)
{
doPluckForNextBuffer.set (false);
prepareSynthesiserState (sampleRate, frequencyInHz);
}
//=======================================================================
/** Excite the simulated string by plucking it at a given position.
@param pluckPosition The position of the plucking, relative to the length
of the string. Must be between 0 and 1.
*/
void stringPlucked (float pluckPosition)
{
jassert (pluckPosition >= 0.0 && pluckPosition <= 1.0);
// we choose a very simple approach to communicate with the audio thread:
// simply tell the synth to perform the plucking excitation at the beginning
// of the next buffer (= when generateAndAddData is called the next time).
if (doPluckForNextBuffer.compareAndSetBool (1, 0))
{
// plucking in the middle gives the largest amplitude;
// plucking at the very ends will do nothing.
amplitude = std::sin (float_Pi * pluckPosition);
}
}
//=======================================================================
/** Generate next chunk of mono audio output and add it into a buffer.
@param outBuffer Buffer to fill (one channel only). New sound will be
added to existing content of the buffer (instead of
replacing it).
@param numSamples Number of samples to generate (make sure that outBuffer
has enough space).
*/
void generateAndAddData (float* outBuffer, int numSamples)
{
if (doPluckForNextBuffer.compareAndSetBool (0, 1))
exciteInternalBuffer();
// cycle through the delay line and apply a simple averaging filter
for (int i = 0; i < numSamples; ++i)
{
const int nextPos = (pos + 1) % delayLine.size();
delayLine[nextPos] = (float) (decay * 0.5 * (delayLine[nextPos] + delayLine[pos]));
outBuffer[i] += delayLine[pos];
pos = nextPos;
}
}
private:
//=======================================================================
void prepareSynthesiserState (double sampleRate, double frequencyInHz)
{
std::size_t delayLineLength = std::lround (sampleRate / frequencyInHz);
// we need a minimum delay line length to get a reasonable synthesis.
// if you hit this assert, increase sample rate or decrease frequency!
jassert (delayLineLength > 50);
delayLine.resize (delayLineLength);
std::fill (delayLine.begin(), delayLine.end(), 0.0f);
excitationSample.resize (delayLineLength);
// as the excitation sample we use random noise between -1 and 1
// (as a simple approximation to a plucking excitation)
std::generate (excitationSample.begin(),
excitationSample.end(),
[] { return (Random::getSystemRandom().nextFloat() * 2.0f) - 1.0f; } );
}
void exciteInternalBuffer()
{
// fill the buffer with the precomputed excitation sound (scaled with amplitude)
jassert (delayLine.size() >= excitationSample.size());
std::transform (excitationSample.begin(),
excitationSample.end(),
delayLine.begin(),
[this] (double sample) { return amplitude * sample; } );
};
//=======================================================================
const double decay = 0.998;
double amplitude = 0.0;
Atomic<int> doPluckForNextBuffer;
std::vector<float> excitationSample, delayLine;
int pos = 0;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StringSynthesiser)
};

Loading…
Cancel
Save