Solved Audio Rendering Running too Quickly
-
I'm rendering an internal MIDI sequence, that triggers samples, to an audio file.
But the rendered file sounds like the transport run insanely fast during the process.
Everything else works as expected. The MIDI playback fine in HISE, and syncs to the DAW's playhead. And the file has all the correct notes…just way too fast.
Some people, over the years, have asked how to do this – if someone helps, I'll post the final working code.
Cheers.
/ ======================== Set up the Transport Handler // Create a Master Clock, and set its cardinality. transportHandler.setEnableGrid(true, 1.0); // Set the Master Clock to synch to the DAW, if its transport is running. transportHandler.setSyncMode(transportHandler.PreferExternal); // Set the internal clock bpm to the DAW bpm. Engine.setHostBpm(120.0); // Reset internal clock. transportHandler.stopInternalClockOnExternalStop(true); transportHandler.stopInternalClock(0); // Even though our internal and external bpms are the same, we'll do this. transportHandler.setLinkBpmToSyncMode(true); // ======================== Set Up the MIDI Player // Set the MIDI Player to synch to the Master Clock. This synchs the // DAW transport and playhead. midiplayer_COMPOSER_Playback.setSyncToMasterClock(true); // Use ticks instead of samples, because who knows what the sample rate // might be, midiplayer_COMPOSER_Playback.setUseTimestampInTicks(true); // ======================== Panel to Hold the Buffer const var panel_ENCODER_AudioFileDragPoint_GUI = Content.getComponent("panel_ENCODER_AudioFileDragPoint_GUI"); // ======================== Momentary Button to Read the File const var button_readMidiFile = Content.getComponent("button_readMidiFile"); button_readMidiFile.setControlCallback(onReadMidiFile); inline function onReadMidiFile(component, value) { // Read the MIDI file. midiplayer_COMPOSER_Playback.setFile("{PROJECT_FOLDER}dual_drum_snare_snare1_accents.mid", true, true); }; // ======================== Momentary Button to Write the File const var button_writeMidiFile = Content.getComponent("button_writeMidiFile"); button_writeMidiFile.setControlCallback(onWriteMidiFile); inline function onWriteMidiFile(component, value) { if (value) COMPOSER_RenderMidiToAudio(); }; // ======================== Instigate the Render inline function COMPOSER_RenderMidiToAudio () { // Check if sequencer number one is empty. For some reason, there always seems to be a // sequencer number one, regardless of whether I've imported anything. if (midiplayer_COMPOSER_Playback.isSequenceEmpty(1) != true) { Engine.renderAudio(midiplayer_COMPOSER_Playback.getEventListFromSequence(1), COMPOSER_RenderAudioCallback); } } // ======================== HISE Rendering API Callback inline function COMPOSER_RenderAudioCallback (obj) { // Query to see if finished. local isFinished = obj.finished; // Monitor the progress to ensure we're still running. local progress = obj.progress; Console.print( "Progress: " + progress); // If the rendering completed, write the file. if (isFinished) { // Store the buffer in a Panel's data slot. panel_ENCODER_AudioFileDragPoint_GUI.data.buffer = obj.channels; // Get a reference to the audio folder. local audioFilesDirectory = FileSystem.getFolder(FileSystem.AudioFiles); // Assign a temporary variable to hold the buffer (because this will be moved to another function if/when it works). local bufferToWrite = panel_ENCODER_AudioFileDragPoint_GUI.data.buffer; // Create the new file and get a reference to it. local fileToExport = audioFilesDirectory.getChildFile("test.wav"); // See if the file is mono or stereo. local isMultiChannel = isDefined(bufferToWrite[0].length); // Write the file at whatever sample rate is in fashion, at 16 bits/ if (!isMultiChannel) // Write a mono file. fileToExport.writeAudioFile([bufferToWrite], Engine.getSampleRate(), 16); else // Write a stereo file. fileToExport.writeAudioFile(bufferToWrite, Engine.getSampleRate(), 16); // Relax with frosty beverage? Console.print('DONE!'); } }
-
@clevername27 said in Audio Rendering Running too Quickly:
// Use ticks instead of samples, because who knows what the sample rate
// might be,
midiplayer_COMPOSER_Playback.setUseTimestampInTicks(true);I need to dig into the example properly, but that line might be the culprit. When you pass an event list into the
Engine.renderAudio()
call, it expects it to be timestamped using the sample domain, so a tick based MIDI sequence will run way too fast. Does it help if you omit this line? -
@Christoph-Hart That did it - thank you.
-