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