1 /* 2 ============================================================================== 3 4 This file is part of the JUCE examples. 5 Copyright (c) 2020 - Raw Material Software Limited 6 7 The code included in this file is provided under the terms of the ISC license 8 http://www.isc.org/downloads/software-support-policy/isc-license. Permission 9 To use, copy, modify, and/or distribute this software for any purpose with or 10 without fee is hereby granted provided that the above copyright notice and 11 this permission notice appear in all copies. 12 13 THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, 14 WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR 15 PURPOSE, ARE DISCLAIMED. 16 17 ============================================================================== 18 */ 19 20 /******************************************************************************* 21 The block below describes the properties of this PIP. A PIP is a short snippet 22 of code that can be read by the Projucer and used to generate a JUCE project. 23 24 BEGIN_JUCE_PIP_METADATA 25 26 name: AudioAppDemo 27 version: 1.0.0 28 vendor: JUCE 29 website: http://juce.com 30 description: Simple audio application. 31 32 dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, 33 juce_audio_processors, juce_audio_utils, juce_core, 34 juce_data_structures, juce_events, juce_graphics, 35 juce_gui_basics, juce_gui_extra 36 exporters: xcode_mac, vs2019, linux_make, androidstudio, xcode_iphone 37 38 moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 39 40 type: Component 41 mainClass: AudioAppDemo 42 43 useLocalCopy: 1 44 45 END_JUCE_PIP_METADATA 46 47 *******************************************************************************/ 48 49 #pragma once 50 51 52 //============================================================================== 53 class AudioAppDemo : public AudioAppComponent 54 { 55 public: 56 //============================================================================== AudioAppDemo()57 AudioAppDemo() 58 #ifdef JUCE_DEMO_RUNNER 59 : AudioAppComponent (getSharedAudioDeviceManager (0, 2)) 60 #endif 61 { 62 setAudioChannels (0, 2); 63 64 setSize (800, 600); 65 } 66 ~AudioAppDemo()67 ~AudioAppDemo() override 68 { 69 shutdownAudio(); 70 } 71 72 //============================================================================== prepareToPlay(int samplesPerBlockExpected,double newSampleRate)73 void prepareToPlay (int samplesPerBlockExpected, double newSampleRate) override 74 { 75 sampleRate = newSampleRate; 76 expectedSamplesPerBlock = samplesPerBlockExpected; 77 } 78 79 /* This method generates the actual audio samples. 80 In this example the buffer is filled with a sine wave whose frequency and 81 amplitude are controlled by the mouse position. 82 */ getNextAudioBlock(const AudioSourceChannelInfo & bufferToFill)83 void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override 84 { 85 bufferToFill.clearActiveBufferRegion(); 86 auto originalPhase = phase; 87 88 for (auto chan = 0; chan < bufferToFill.buffer->getNumChannels(); ++chan) 89 { 90 phase = originalPhase; 91 92 auto* channelData = bufferToFill.buffer->getWritePointer (chan, bufferToFill.startSample); 93 94 for (auto i = 0; i < bufferToFill.numSamples ; ++i) 95 { 96 channelData[i] = amplitude * std::sin (phase); 97 98 // increment the phase step for the next sample 99 phase = std::fmod (phase + phaseDelta, MathConstants<float>::twoPi); 100 } 101 } 102 } 103 releaseResources()104 void releaseResources() override 105 { 106 // This gets automatically called when audio device parameters change 107 // or device is restarted. 108 } 109 110 111 //============================================================================== paint(Graphics & g)112 void paint (Graphics& g) override 113 { 114 // (Our component is opaque, so we must completely fill the background with a solid colour) 115 g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId)); 116 117 auto centreY = (float) getHeight() / 2.0f; 118 auto radius = amplitude * 200.0f; 119 120 if (radius >= 0.0f) 121 { 122 // Draw an ellipse based on the mouse position and audio volume 123 g.setColour (Colours::lightgreen); 124 125 g.fillEllipse (jmax (0.0f, lastMousePosition.x) - radius / 2.0f, 126 jmax (0.0f, lastMousePosition.y) - radius / 2.0f, 127 radius, radius); 128 } 129 130 // Draw a representative sine wave. 131 Path wavePath; 132 wavePath.startNewSubPath (0, centreY); 133 134 for (auto x = 1.0f; x < (float) getWidth(); ++x) 135 wavePath.lineTo (x, centreY + amplitude * (float) getHeight() * 2.0f 136 * std::sin (x * frequency * 0.0001f)); 137 138 g.setColour (getLookAndFeel().findColour (Slider::thumbColourId)); 139 g.strokePath (wavePath, PathStrokeType (2.0f)); 140 } 141 142 // Mouse handling.. mouseDown(const MouseEvent & e)143 void mouseDown (const MouseEvent& e) override 144 { 145 mouseDrag (e); 146 } 147 mouseDrag(const MouseEvent & e)148 void mouseDrag (const MouseEvent& e) override 149 { 150 lastMousePosition = e.position; 151 152 frequency = (float) (getHeight() - e.y) * 10.0f; 153 amplitude = jmin (0.9f, 0.2f * e.position.x / (float) getWidth()); 154 155 phaseDelta = (float) (MathConstants<double>::twoPi * frequency / sampleRate); 156 157 repaint(); 158 } 159 mouseUp(const MouseEvent &)160 void mouseUp (const MouseEvent&) override 161 { 162 amplitude = 0.0f; 163 repaint(); 164 } 165 resized()166 void resized() override 167 { 168 // This is called when the component is resized. 169 // If you add any child components, this is where you should 170 // update their positions. 171 } 172 173 174 private: 175 //============================================================================== 176 float phase = 0.0f; 177 float phaseDelta = 0.0f; 178 float frequency = 5000.0f; 179 float amplitude = 0.2f; 180 181 double sampleRate = 0.0; 182 int expectedSamplesPerBlock = 0; 183 Point<float> lastMousePosition; 184 185 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioAppDemo) 186 }; 187