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