Nope, there isn’t However, I’m sure it could be rebuilt from scratch and all, but the functionality must stay the same.
Here is what Record to Current Track does. When you call it via Midi Mapping, or via Key Binding, or via Menu Entry. It starts recording. (Your Sample Recorder MUST be in Pattern Sync and “do not create a new sample” mode.)
When you press the midibutton, menuentry or keybind again, it stops recording. It will stop recording at the end of that pattern that is playing.
The minute the samplebuffer has been filled with what you recorded, the instrument number is put to the pattern editor, to your selected_track. a 0501 effect (Glide to note) is put in. Why? Because if there’s a 0501 on that same row, you can record 10 times the pattern, or 100 times the pattern length, and when the pattern starts playing the sample, it will play it until the end of the sample. then the next pattern-toggle-of-this-sample will re-start the playing. This gives me a handy way of having a short, or long pattern, where I have multiple length wavefiles playing at the same time. It means that if I have a 32 row pattern, I can record 512 rows of sample_data, and when i stop recording, it will start playing, and after 16 repetitions of the 32 row pattern, the 512 rows of sampledata have been played till the end, and the 17th repeat of the 32 row pattern will restart the sample again.
Now, when you record for the first time, your track title is renamed to “_1”. When you then record again on the same track, a second note_column is made visible, and the note is placed there. If you have all 12 note columns visible, and have notes in notecolumn 2-12, the Record_To_Current_Track will place the next note to notecolumn 1.
The renaming till Tracktitle “_12” is there so that once the RecordToCurrentTrack recognizes that the name of the track is “_12”, it will automatically switch to the next, new track, and sample to that, instead.
So basically this is a way for me to go completely blind with Renoise, to have either a keyboard shortcut or a midibutton which will start sampling, or will stop sampling.
When you start sampling, the sample_recorder is opened. When you stop sampling (with the same keyshortcut/midimap), the sample_recorder is hidden. Thus you don’t have to look at samplerecorder, you can just focus on sampling as many some-length samples as you want, and they will be put in, you can just stop looking at the screen.
This allows me to sample anything I play on the microphone, any outboard synthesizer, and can multilayer them as i want.
There are checks to make sure no midi-instrument, plugin instrument, or sample are overwritten. the real hassle of the code is to make sure that only one keyshortcut/midimap is required to both start AND stop recording, this is very important.
Ihad to have a finalrecord, in order to have notifiers that run finalrecord and then the notifier is removed. There was some reason for this - i wanted to use a notifier for “when samplebuffer is changed”, so that I could somehow provide, for instance Jenoki, with the method of "when you stop recording, there’s a quick panic() and a quick play - so that the minute you stop recording, the sample will start playing).
This one is pretty convoluted. If you record 128 rows’ worth of sampledata in a 64 row pattern, the recording process will take 2 repeats of the 64 rows. but the sample_loading process will take 1 repeat of the 64 row pattern. i was trying to fix it so that when you stop recording, the sample starts playing immediately. I kind of got it working, or didn’t, but it grew really convoluted and did not seem to work, i tried a few methods of making it work that i knew how to do, but swiftly gave up.
when you start recording, the bottom layer is switched to automation. Why? Because then you can see a playhead and see when you must be ready to play something in, i.e. “how long will it take until my pattern synced recording starts - well, automation playhead shows that it’ll be one second, so i’d better be ready.”
When the sample has been recorded, autoseek is set to mode=on
finalrecord does the 0501 writing to that selected_track_index.
c-4 is written to the selected_track_index first row, so that the sample you’ve just recorded will start playing. the instrument_index is written to the first row of the pattern too.
I did some minor modifications, where, if playback is off, playback is switched On, so that recording may start. again, i’m going for complete transparency. one shortcut and i’m sampling, no matter if the song is playing or not. one shortcut and i’ve stopped sampling and i can start hearing what i sampled, and maybe layer something on top of that.
For those max.12 notecolumns to be written to only if they’re empty, there’s a check for notecolumn - does any of the 12 notecolumns have a — on the first row? If yes, then write to that.
Now, there are some bugs with this, which I discovered later on, such as, if I’ve already played something into a pattern, but the first row is empty, a sample will be placed there, but it will stop playing if that notecolumn has notes on another row. So I suppose one would have to check if the notecolumn is fully empty, before committing to writing anything to it.
The “_12”? Go to next track is probably pretty clunky, but I got it to work and was pretty proud of it, to be honest.
–
This is one way (I commented off some code) to try and restart playback immediately after recording:
renoise.tool():add_midi_mapping{name="Paketti:Record to Current Track x[Toggle]", invoke = function() recordtocurrenttrack()
if renoise.song().transport.playing==false then renoise.song().transport.playing=true end
local seq=renoise.song().selected_sequence_index
local startpos = renoise.song().transport.playback_pos
local t=renoise.song().transport
t.loop_block_enabled=false
--t:panic()
--startpos.line = renoise.song().selected_line_index
--startpos.sequence = renoise.song().selected_sequence_index
--renoise.song().transport.playback_pos = startpos
--t:start(renoise.Transport.PLAYMODE_CONTINUE_PATTERN)
renoise.song().transport.follow_player=true
renoise.app().window.active_lower_frame=2
renoise.app().window.lower_frame_is_visible=true
end}
Another version I tried to do was
renoise.tool():add_keybinding {name="Global:Paketti:Record to Current Track", invoke = function() recordtocurrenttrack()
search_empty_instrument()
if renoise.song().transport.playing==false then renoise.song().transport.playing=true end
local seq=renoise.song().selected_sequence_index
local startpos = renoise.song().transport.playback_pos
local t=renoise.song().transport
renoise.song().transport.follow_player=true
--t:panic()
t.loop_block_enabled=false
--startpos.line = renoise.song().selected_line_index
--startpos.sequence = renoise.song().selected_sequence_index
--renoise.song().transport.playback_pos = startpos
--t:start(renoise.Transport.PLAYMODE_CONTINUE_PATTERN)
renoise.song().transport.follow_player=true
renoise.app().window.lower_frame_is_visible=true
renoise.app().window.active_lower_frame=2
end}
But decided to comment it all away. For, you see, when you start messing around with “stop playback” while a sample is being written, the sample might get some extra data, so a 128 row sample might be 129 row length, and then it won’t play nicely on the 3rd repeat of a 64 row pattern. Things got really fiddly, and when you do a panic and a restart, the multilayered things you had playing will stop and restart - when fidddling with the “start playback after sampling”, it turned out to not be a good solution. It has to be visually functional (i.e. no need to look) and functional audio-wise (no sound stops).
--This records to currently selected track and outputs 0501 and the c-4 and the selected_instrument
function recordtocurrenttrack()
local s=renoise.song()
local ss=s.selected_sample
local t=renoise.song().transport
local w=renoise.app().window
local currTrak=s.selected_track_index
local currSamp=renoise.song().selected_sample_index
if renoise.song().transport.playing==false then
renoise.song().transport.playing=true end
local name = nil
if renoise.song().selected_track_index<10 then
name="Track 0"..renoise.song().selected_track_index
else
name="Track "..renoise.song().selected_track_index
end
if renoise.song().tracks[currTrak].name==name
then renoise.song().tracks[currTrak].name=" 1"
end
if renoise.song().tracks[currTrak].name==" 12" then
local nexttrack=renoise.song().selected_track_index+1
renoise.song():insert_track_at(nexttrack)
renoise.song().selected_track_index=renoise.song().selected_track_index+1
renoise.song().tracks[renoise.song().selected_track_index].name=" 1"
end
s.selected_instrument_index = search_empty_instrument()
w.sample_record_dialog_is_visible=true
t:start_stop_sample_recording()
if ss.sample_buffer_observable:has_notifier(finalrecord) == false then
ss.sample_buffer_observable:add_notifier(finalrecord)
end
-- delay(3)
-- renoise.song().transport:trigger_sequence(1)
end
function finalrecord()
local s=renoise.song()
local ss=s.selected_sample
local currTrak=s.selected_track_index
local currSamp=renoise.song().selected_sample_index
local currInst=s.selected_instrument_index
local currPatt=s.selected_pattern_index
local w=renoise.app().window
local rightinstrument=nil
local place=nil
local zero=nil
local o=nil
local rightinstrument=renoise.song().selected_instrument_index-1
local nc=s.patterns[currPatt].tracks[currTrak].lines[1].note_columns
local selnotcol=renoise.song().selected_note_column_index
local vnc=renoise.song().tracks[currTrak].visible_note_columns
w.active_lower_frame=2
w.sample_record_dialog_is_visible=false
ss.autoseek=true
s.patterns[currPatt].tracks[currTrak].lines[1].effect_columns[1].number_string="05"
s.patterns[currPatt].tracks[currTrak].lines[1].effect_columns[1].amount_string="01"
for o = 1,12 do
if nc[o].note_string=="---" then
s.patterns[currPatt].tracks[currTrak].lines[1].note_columns[o].note_string="C-4"
s.patterns[currPatt].tracks[currTrak].lines[1].note_columns[o].instrument_value=rightinstrument
if vnc < o then
s.tracks[currTrak].visible_note_columns=o
renoise.song().tracks[currTrak].name=" " .. o
end
break
end
end
local t=renoise.song().transport
local seq=renoise.song().selected_sequence_index
local startpos = renoise.song().transport.playback_pos
--t:panic()
--t:start(renoise.Transport.PLAYMODE_RESTART_PATTERN)
-- startpos.line = renoise.song().selected_line_index
-- startpos.sequence = renoise.song().selected_sequence_index
-- renoise.song().transport.playback_pos = startpos
-- t:start(renoise.Transport.PLAYMODE_CONTINUE_PATTERN)
-- ss.sample_buffer_observable:remove_notifier(finalrecord)
end
renoise.tool():add_midi_mapping{name="Paketti:Record to Current Track x[Toggle]", invoke = function() recordtocurrenttrack()
if renoise.song().transport.playing==false then renoise.song().transport.playing=true end
local seq=renoise.song().selected_sequence_index
local startpos = renoise.song().transport.playback_pos
local t=renoise.song().transport
t.loop_block_enabled=false
--t:panic()
--startpos.line = renoise.song().selected_line_index
--startpos.sequence = renoise.song().selected_sequence_index
--renoise.song().transport.playback_pos = startpos
--t:start(renoise.Transport.PLAYMODE_CONTINUE_PATTERN)
renoise.song().transport.follow_player=true
renoise.app().window.active_lower_frame=2
renoise.app().window.lower_frame_is_visible=true
end}
--renoise.tool():add_menu_entry {name="Pattern Editor:Record To Current", invoke = function() recordtocurrenttrack() end}
--renoise.tool():add_menu_entry {name="Mixer:RecordToCurrent", invoke = function() recordtocurrenttrack() end}
--renoise.tool():add_menu_entry {name="Instrument Box:Record To Current", invoke = function() recordtocurrenttrack() end}
--renoise.tool():add_menu_entry {name="Sample Editor:Record To Current", invoke = function() recordtocurrenttrack() end}
renoise.tool():add_menu_entry {name="Sample Mappings:Record To Current", invoke = function() recordtocurrenttrack() end}
renoise.tool():add_keybinding {name="Global:Paketti:Record to Current Track", invoke = function() recordtocurrenttrack()
search_empty_instrument()
if renoise.song().transport.playing==false then renoise.song().transport.playing=true end
local seq=renoise.song().selected_sequence_index
local startpos = renoise.song().transport.playback_pos
local t=renoise.song().transport
renoise.song().transport.follow_player=true
--t:panic()
t.loop_block_enabled=false
--startpos.line = renoise.song().selected_line_index
--startpos.sequence = renoise.song().selected_sequence_index
--renoise.song().transport.playback_pos = startpos
--t:start(renoise.Transport.PLAYMODE_CONTINUE_PATTERN)
renoise.song().transport.follow_player=true
renoise.app().window.lower_frame_is_visible=true
renoise.app().window.active_lower_frame=2
end}
-- and vV's nice code to detect:
function search_empty_instrument()
local proc = renoise.song()
for empty_instrument = 1, #proc.instruments do
local samples = false
for i = 1,#proc.instruments[empty_instrument].samples do
local temp_buffer = proc.instruments[empty_instrument].samples[i].sample_buffer
if temp_buffer.has_sample_data then
samples = true
break
end
end
local plugin = proc.instruments[empty_instrument].plugin_properties.plugin_loaded
local midi_device = proc.instruments[empty_instrument].midi_output_properties.device_name
if ((samples == false) and (plugin == false) and
(midi_device == nil or midi_device == "")) then
return empty_instrument
end
end
proc:insert_instrument_at(#proc.instruments+1)
return #proc.instruments
end
What exactly do I want to do with this? I just wanna be free.
And so far it’s working. now with vV’s fix that enables me to stop overwriting midi-instruments and plugin-instruments, it’s really quite close to being finished, apart from the “will only toggle on second repeat of the pattern” which kind of makes stuff real weird.
I was trying to recreate the way Ableton Live works in the Session View, which is to afford the user the possibility of having a looping sample that plays for 1 bar and repeats, or a looping sample which plays for 1024 bars and then repeats, and then be able to hear both continuously, even tho the pattern might be 4 bars in length. I could make a video of how it works right now, but I’m not sure if it would explain something which this message hasn’t already explained.
The issue, of course, is that currently there’s no way of setting the sample_recorder to PatternSync. and no way to control which channel the sample_recorder samples from. I do hope that these functions will come in future API updates, since, well, I’m already breaking into a second script (which gives me shortcuts which immediately auto-configure a midi-instrument and a line-in-device to the correct input - and renames the track to a specific name (so I can just hear-what-the-synths-are-playing directly within Renoise and be able to run them through efx. Once I can use the API to set the sample recorder to conform to the line-in-device’s input channels, maybe some observable of “you are on channel called Alphajuno2 → switch sample_recorder to alphajuno2 input channel, what’s the input channel? read it from alphajuno2-channel’s alphajuno2-line-input-device settings” or something like that.
Come to think of it, the threekeyboard shortcuts (studio electronics se-1, nord micromodular, roland alphajuno2) should probably be modified to use vV’s “go to empty instrument” too, so I don’t end up overwriting them…)
the cherry on the top would be to actually read the tracks and remove a line-input-device-for-synthX when the lineinput device is added to a separate track. This I still have to do by hand (the removal of lineinput device, not the adding of input device, of course ).
mxb was this verbose enough for you to kind of get what record_to_current_track does?
some people wanted the sample recorder to have a method where after sampling, the instrument is placed to first row of said track, so that one could just easily record stuff and not run into issues of having to reach for the mouse + keyboard to write the instrument number and c-4 to that track. Renoise never provided this natively, so I ended up doing this on my own and fiddling with it and tweaking it until it works pretty much transparently, albeit some bugs.