Azimuth Moderator & Beta Team

Joined: 19 Nov 2010 Posts: 2131
|
Posted: Tue Dec 02, 2025 1:33 pm Post subject: Updated Jamstix 4 Reaper Script with T/S and Tempo (12/2025) |
|
|
The above .gif is over 2 minutes long but I wanted to show the entire process of using the script. Now if you add "<space>x/x<space>:number" after the song part name (without the quotation marks) the script will automatically add time signature markers and tempo changes at the proper locations. The script will use the previous marker's tempo or 4/4 if no time signature or tempo is specified.
I wanted to check out what it was like working with an AI assistant so I decided to try it out. This version was coded using MS Copilot so I take no credit other than guiding it with what I wanted. Hope that you can find some use for the update. Feel free to comment or make suggestions if you'd like. I'm going to delete the posts with the earlier versions since this contains the same functionality and has been reliable so far in my testing.
| Code: | ---------------------------------------------------------------------
-- CLEANUP: Delete all existing markers, tempo/TS markers, and regions
---------------------------------------------------------------------
local function clear_project_markers()
-- SWS: delete all markers and regions
local del_all_markers_regions = reaper.NamedCommandLookup("_SWSMARKERLIST9")
if del_all_markers_regions ~= 0 then
reaper.Main_OnCommand(del_all_markers_regions, 0)
end
-- SWS: delete all regions (explicit)
local del_all_regions = reaper.NamedCommandLookup("_SWSMARKERLIST10")
if del_all_regions ~= 0 then
reaper.Main_OnCommand(del_all_regions, 0)
end
-- Delete all tempo/time signature markers
local numTempoMarkers = reaper.CountTempoTimeSigMarkers(0)
for i = numTempoMarkers - 1, 0, -1 do
reaper.DeleteTempoTimeSigMarker(0, i)
end
end
clear_project_markers()
---------------------------------------------------------------------
-- INSERT JAMSTIX MIDI AT START OF PROJECT ON NEW LAST TRACK
---------------------------------------------------------------------
local midi_path = "C:\\ProgramData\\Jamstix4\\jamstix.mid"
local track_index = reaper.CountTracks(0)
reaper.InsertTrackAtIndex(track_index, true)
local new_track = reaper.GetTrack(0, track_index)
reaper.SetOnlyTrackSelected(new_track)
reaper.SetEditCurPos(0, true, false)
reaper.InsertMedia(midi_path, 0)
-- Adjust track list windows
reaper.TrackList_AdjustWindows(false)
---------------------------------------------------------------------
-- Function: Read all markers fresh from the project (updated positions)
---------------------------------------------------------------------
local function read_markers()
local t = {}
local _, numMarkers, numRegions = reaper.CountProjectMarkers(0)
local total = numMarkers + numRegions
local function parse_marker_name(full)
local cleaned = full:gsub("%[%d+%]", "")
local ts = cleaned:match("(%d+/%d+)")
local bpm = cleaned:match(":(%d+)")
local name = cleaned
name = name:gsub("%d+/%d+", "")
name = name:gsub(":%d+", "")
name = name:match("^%s*(.-)%s*$")
return name, ts, bpm
end
for i = 0, total - 1 do
local ok, isRegion, pos, _, name, idx = reaper.EnumProjectMarkers(i)
if ok and not isRegion then
local regionName, ts, tempoStr = parse_marker_name(name or "")
local num, den
if ts then
num, den = ts:match("(%d+)/(%d+)")
num = tonumber(num)
den = tonumber(den)
end
local bpm = tempoStr and tonumber(tempoStr) or nil
table.insert(t, {
name = regionName,
pos = pos,
ts_num = num,
ts_den = den,
bpm = bpm,
idx = idx
})
end
end
table.sort(t, function(a, b) return a.pos < b.pos end)
return t
end
---------------------------------------------------------------------
-- INITIAL READ OF ALL MARKERS
---------------------------------------------------------------------
markers = read_markers()
---------------------------------------------------------------------
-- INSERT TEMPO/TIME SIGNATURE MARKERS ONE BY ONE
---------------------------------------------------------------------
local function sleep(ms)
local t = os.clock()
while (os.clock() - t) < (ms / 1000) do end
end
reaper.PreventUIRefresh(1)
local a = 1
while a <= #markers do
local m = markers[a]
local ts_num = m.ts_num or 4
local ts_den = m.ts_den or 4
if m.bpm then
reaper.SetTempoTimeSigMarker(-1, -1, m.pos, -1, -1, m.bpm, ts_num, ts_den, 0)
else
reaper.SetTempoTimeSigMarker(-1, -1, m.pos, -1, -1, -1, ts_num, ts_den, 0)
end
-- 1ms delay to allow REAPER to update before next insertion
sleep(1)
-- Rebuild marker list to get UPDATED positions
markers = read_markers()
a = a + 1
end
reaper.PreventUIRefresh(-1)
---------------------------------------------------------------------
-- CONVERT ALL MARKERS TO REGIONS (SWS)
---------------------------------------------------------------------
local convert_cmd = reaper.NamedCommandLookup("_SWSMARKERLIST13")
if convert_cmd ~= 0 then
reaper.Main_OnCommand(convert_cmd, 0)
end
---------------------------------------------------------------------
-- FORCE PROJECT VIEW/TIMELINE UPDATE
---------------------------------------------------------------------
reaper.UpdateTimeline()
reaper.UpdateArrange()
---------------------------------------------------------------------
-- CLEANUP: DELETE THE TEMPORARY TRACK AND REWIND TO START
---------------------------------------------------------------------
if new_track then
reaper.DeleteTrack(new_track)
end
-- Rewind edit cursor to start of project
reaper.SetEditCurPos(0, true, false)
|
|
|