The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 lines
10KB

  1. /*
  2. ==============================================================================
  3. This is an automatically generated GUI class created by the Introjucer!
  4. Be careful when adding custom code to these files, as only the code within
  5. the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
  6. and re-saved.
  7. Created with Introjucer version: 3.1.0
  8. ------------------------------------------------------------------------------
  9. The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
  10. Copyright 2004-13 by Raw Material Software Ltd.
  11. ==============================================================================
  12. */
  13. //[Headers] You can add your own extra header files here...
  14. //[/Headers]
  15. #include "AudioDemoRecordPage.h"
  16. //[MiscUserDefs] You can add your own user definitions and misc code here...
  17. //==============================================================================
  18. /** A simple class that acts as an AudioIODeviceCallback and writes the
  19. incoming audio data to a WAV file.
  20. */
  21. class AudioRecorder : public AudioIODeviceCallback
  22. {
  23. public:
  24. AudioRecorder()
  25. : backgroundThread ("Audio Recorder Thread"),
  26. sampleRate (0), activeWriter (0)
  27. {
  28. backgroundThread.startThread();
  29. }
  30. ~AudioRecorder()
  31. {
  32. stop();
  33. }
  34. //==============================================================================
  35. void startRecording (const File& file)
  36. {
  37. stop();
  38. if (sampleRate > 0)
  39. {
  40. // Create an OutputStream to write to our destination file...
  41. file.deleteFile();
  42. ScopedPointer<FileOutputStream> fileStream (file.createOutputStream());
  43. if (fileStream != 0)
  44. {
  45. // Now create a WAV writer object that writes to our output stream...
  46. WavAudioFormat wavFormat;
  47. AudioFormatWriter* writer = wavFormat.createWriterFor (fileStream, sampleRate, 1, 16, StringPairArray(), 0);
  48. if (writer != 0)
  49. {
  50. fileStream.release(); // (passes responsibility for deleting the stream to the writer object that is now using it)
  51. // Now we'll create one of these helper objects which will act as a FIFO buffer, and will
  52. // write the data to disk on our background thread.
  53. threadedWriter = new AudioFormatWriter::ThreadedWriter (writer, backgroundThread, 32768);
  54. // And now, swap over our active writer pointer so that the audio callback will start using it..
  55. const ScopedLock sl (writerLock);
  56. activeWriter = threadedWriter;
  57. }
  58. }
  59. }
  60. }
  61. void stop()
  62. {
  63. // First, clear this pointer to stop the audio callback from using our writer object..
  64. {
  65. const ScopedLock sl (writerLock);
  66. activeWriter = 0;
  67. }
  68. // Now we can delete the writer object. It's done in this order because the deletion could
  69. // take a little time while remaining data gets flushed to disk, so it's best to avoid blocking
  70. // the audio callback while this happens.
  71. threadedWriter = 0;
  72. }
  73. bool isRecording() const
  74. {
  75. return activeWriter != 0;
  76. }
  77. //==============================================================================
  78. void audioDeviceAboutToStart (AudioIODevice* device)
  79. {
  80. sampleRate = device->getCurrentSampleRate();
  81. }
  82. void audioDeviceStopped()
  83. {
  84. sampleRate = 0;
  85. }
  86. void audioDeviceIOCallback (const float** inputChannelData, int /*numInputChannels*/,
  87. float** outputChannelData, int numOutputChannels,
  88. int numSamples)
  89. {
  90. const ScopedLock sl (writerLock);
  91. if (activeWriter != 0)
  92. activeWriter->write (inputChannelData, numSamples);
  93. // We need to clear the output buffers, in case they're full of junk..
  94. for (int i = 0; i < numOutputChannels; ++i)
  95. if (outputChannelData[i] != 0)
  96. zeromem (outputChannelData[i], sizeof (float) * (size_t) numSamples);
  97. }
  98. private:
  99. TimeSliceThread backgroundThread; // the thread that will write our audio data to disk
  100. ScopedPointer<AudioFormatWriter::ThreadedWriter> threadedWriter; // the FIFO used to buffer the incoming data
  101. double sampleRate;
  102. CriticalSection writerLock;
  103. AudioFormatWriter::ThreadedWriter* volatile activeWriter;
  104. };
  105. //[/MiscUserDefs]
  106. //==============================================================================
  107. AudioDemoRecordPage::AudioDemoRecordPage (AudioDeviceManager& deviceManager_)
  108. : deviceManager (deviceManager_)
  109. {
  110. addAndMakeVisible (liveAudioDisplayComp = new LiveAudioInputDisplayComp());
  111. addAndMakeVisible (explanationLabel = new Label (String::empty,
  112. "This page demonstrates how to record a wave file from the live audio input..\n\nPressing record will start recording a file in your \"Documents\" folder."));
  113. explanationLabel->setFont (Font (15.00f, Font::plain));
  114. explanationLabel->setJustificationType (Justification::topLeft);
  115. explanationLabel->setEditable (false, false, false);
  116. explanationLabel->setColour (TextEditor::textColourId, Colours::black);
  117. explanationLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
  118. addAndMakeVisible (recordButton = new TextButton (String::empty));
  119. recordButton->setButtonText ("Record");
  120. recordButton->addListener (this);
  121. recordButton->setColour (TextButton::buttonColourId, Colour (0xffff5c5c));
  122. recordButton->setColour (TextButton::textColourOnId, Colours::black);
  123. //[UserPreSize]
  124. //[/UserPreSize]
  125. setSize (600, 400);
  126. //[Constructor] You can add your own custom stuff here..
  127. recorder = new AudioRecorder();
  128. deviceManager.addAudioCallback (recorder);
  129. deviceManager.addAudioCallback (liveAudioDisplayComp);
  130. //[/Constructor]
  131. }
  132. AudioDemoRecordPage::~AudioDemoRecordPage()
  133. {
  134. //[Destructor_pre]. You can add your own custom destruction code here..
  135. deviceManager.removeAudioCallback (recorder);
  136. deviceManager.removeAudioCallback (liveAudioDisplayComp);
  137. recorder = 0;
  138. //[/Destructor_pre]
  139. liveAudioDisplayComp = nullptr;
  140. explanationLabel = nullptr;
  141. recordButton = nullptr;
  142. //[Destructor]. You can add your own custom destruction code here..
  143. //[/Destructor]
  144. }
  145. //==============================================================================
  146. void AudioDemoRecordPage::paint (Graphics& g)
  147. {
  148. //[UserPrePaint] Add your own custom painting code here..
  149. //[/UserPrePaint]
  150. g.fillAll (Colours::lightgrey);
  151. //[UserPaint] Add your own custom painting code here..
  152. //[/UserPaint]
  153. }
  154. void AudioDemoRecordPage::resized()
  155. {
  156. liveAudioDisplayComp->setBounds (8, 8, getWidth() - 16, 64);
  157. explanationLabel->setBounds (160, 88, getWidth() - 169, 216);
  158. recordButton->setBounds (8, 88, 136, 40);
  159. //[UserResized] Add your own custom resize handling here..
  160. //[/UserResized]
  161. }
  162. void AudioDemoRecordPage::buttonClicked (Button* buttonThatWasClicked)
  163. {
  164. //[UserbuttonClicked_Pre]
  165. //[/UserbuttonClicked_Pre]
  166. if (buttonThatWasClicked == recordButton)
  167. {
  168. //[UserButtonCode_recordButton] -- add your button handler code here..
  169. if (recorder->isRecording())
  170. {
  171. recorder->stop();
  172. }
  173. else
  174. {
  175. File file (File::getSpecialLocation (File::userDocumentsDirectory)
  176. .getNonexistentChildFile ("Juce Demo Audio Recording", ".wav"));
  177. recorder->startRecording (file);
  178. }
  179. if (recorder->isRecording())
  180. recordButton->setButtonText ("Stop");
  181. else
  182. recordButton->setButtonText ("Record");
  183. //[/UserButtonCode_recordButton]
  184. }
  185. //[UserbuttonClicked_Post]
  186. //[/UserbuttonClicked_Post]
  187. }
  188. void AudioDemoRecordPage::visibilityChanged()
  189. {
  190. //[UserCode_visibilityChanged] -- Add your code here...
  191. recorder->stop();
  192. recordButton->setButtonText ("Record");
  193. //[/UserCode_visibilityChanged]
  194. }
  195. //[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
  196. //[/MiscUserCode]
  197. //==============================================================================
  198. #if 0
  199. /* -- Introjucer information section --
  200. This is where the Introjucer stores the metadata that describe this GUI layout, so
  201. make changes in here at your peril!
  202. BEGIN_JUCER_METADATA
  203. <JUCER_COMPONENT documentType="Component" className="AudioDemoRecordPage" componentName=""
  204. parentClasses="public Component" constructorParams="AudioDeviceManager&amp; deviceManager_"
  205. variableInitialisers="deviceManager (deviceManager_)" snapPixels="8"
  206. snapActive="1" snapShown="1" overlayOpacity="0.330" fixedSize="0"
  207. initialWidth="600" initialHeight="400">
  208. <METHODS>
  209. <METHOD name="visibilityChanged()"/>
  210. </METHODS>
  211. <BACKGROUND backgroundColour="ffd3d3d3"/>
  212. <GENERICCOMPONENT name="" id="7d70eb2617f56220" memberName="liveAudioDisplayComp"
  213. virtualName="" explicitFocusOrder="0" pos="8 8 16M 64" class="LiveAudioInputDisplayComp"
  214. params=""/>
  215. <LABEL name="" id="1162fb2599a768b4" memberName="explanationLabel" virtualName=""
  216. explicitFocusOrder="0" pos="160 88 169M 216" edTextCol="ff000000"
  217. edBkgCol="0" labelText="This page demonstrates how to record a wave file from the live audio input..&#10;&#10;Pressing record will start recording a file in your &quot;Documents&quot; folder."
  218. editableSingleClick="0" editableDoubleClick="0" focusDiscardsChanges="0"
  219. fontname="Default font" fontsize="15" bold="0" italic="0" justification="9"/>
  220. <TEXTBUTTON name="" id="2c10a0ba9fad39da" memberName="recordButton" virtualName=""
  221. explicitFocusOrder="0" pos="8 88 136 40" bgColOff="ffff5c5c"
  222. textCol="ff000000" buttonText="Record" connectedEdges="0" needsCallback="1"
  223. radioGroupId="0"/>
  224. </JUCER_COMPONENT>
  225. END_JUCER_METADATA
  226. */
  227. #endif
  228. //[EndFile] You can add extra defines here...
  229. //[/EndFile]