update + audio warp/stretch

This commit is contained in:
SatyrDiamond 2023-06-09 20:34:10 -04:00
parent 1c26756ddc
commit 1398e0bbe6
156 changed files with 528 additions and 316 deletions

View file

@ -253,6 +253,10 @@ print('[info] ' + typelist[in_type] + ' > ' + typelist[out_type])
if out_type != 'debug':
CVPJ_j = song_compat.makecompat(CVPJ_j, in_type, in_dawcapabilities, out_dawcapabilities)
if in_type in ['r', 'm']: CVPJ_j = song_compat.makecompat_audiostretch(CVPJ_j, in_type, in_dawcapabilities, out_dawcapabilities)
CVPJ_j = song_compat.makecompat_any(CVPJ_j, in_type, in_dawcapabilities, out_dawcapabilities)
if in_type == 'ri' and out_type == 'mi': CVPJ_j = song_convert.ri2mi(CVPJ_j)
if in_type == 'ri' and out_type == 'r': CVPJ_j = song_convert.ri2r(CVPJ_j)
@ -269,11 +273,12 @@ if in_type == 'mi' and out_type == 'r':
CVPJ_j = song_convert.mi2m(CVPJ_j, extra_json)
CVPJ_j = song_convert.m2r(CVPJ_j)
if out_type != 'debug':
CVPJ_j = song_compat.makecompat(CVPJ_j, out_type, in_dawcapabilities, out_dawcapabilities)
CVPJ_j = song_compat.makecompat_any(CVPJ_j, out_type, in_dawcapabilities, out_dawcapabilities)
if out_type in ['r', 'm']: CVPJ_j = song_compat.makecompat_audiostretch(CVPJ_j, out_type, in_dawcapabilities, out_dawcapabilities)
#CVPJ_j = song_compat.makecompat_any(CVPJ_j, out_type, in_dawcapabilities, out_dawcapabilities)
# ------------------------------------------------------------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------------------------------------------------------------------

0
LICENSE Executable file → Normal file
View file

0
README.md Executable file → Normal file
View file

0
config_vst.py Executable file → Normal file
View file

0
config_vst_windows.py Executable file → Normal file
View file

0
data_idvals/adlib_rol_inst.csv Executable file → Normal file
View file

0
data_idvals/beepbox_inst.csv Executable file → Normal file
View file

0
data_idvals/boscaceoil_drumkit_midi.csv Executable file → Normal file
View file

0
data_idvals/boscaceoil_drumkit_simple.csv Executable file → Normal file
View file

0
data_idvals/boscaceoil_drumkit_sion.csv Executable file → Normal file
View file

0
data_idvals/boscaceoil_inst.csv Executable file → Normal file
View file

0
data_idvals/caustic_inst.csv Executable file → Normal file
View file

0
data_idvals/mariopaint_inst.csv Executable file → Normal file
View file

0
data_idvals/midi_ctrl.csv Executable file → Normal file
View file

0
data_idvals/midi_drumkit.csv Executable file → Normal file
View file

0
data_idvals/midi_inst.csv Executable file → Normal file
View file

0
data_idvals/midi_inst_drums.csv Executable file → Normal file
View file

0
data_idvals/midi_inst_group.csv Executable file → Normal file
View file

0
data_idvals/names_gmmidi.csv Executable file → Normal file
View file

0
data_idvals/names_gmmidi_drums.csv Executable file → Normal file
View file

0
data_idvals/noteblockstudio_inst.csv Executable file → Normal file
View file

0
data_idvals/notessimo_v2_inst.csv Executable file → Normal file
View file

0
data_idvals/notessimo_v3_inst.csv Executable file → Normal file
View file

0
data_idvals/notessimo_v3_inst_group.csv Executable file → Normal file
View file

0
data_idvals/onlineseq_drumkit.csv Executable file → Normal file
View file

0
data_idvals/onlineseq_drumkit_2013.csv Executable file → Normal file
View file

0
data_idvals/onlineseq_drumkit_808.csv Executable file → Normal file
View file

0
data_idvals/onlineseq_drumkit_909.csv Executable file → Normal file
View file

0
data_idvals/onlineseq_drumkit_retro.csv Executable file → Normal file
View file

0
data_idvals/onlineseq_inst.csv Executable file → Normal file
View file

0
data_idvals/orgyana_inst_drums.csv Executable file → Normal file
View file

0
data_idvals/soundclub2_inst.csv Executable file → Normal file
View file

0
dawvert_cmd.py Executable file → Normal file
View file

0
docs/dawvert.svg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 121 KiB

0
docs/experiments.md Executable file → Normal file
View file

0
docs/input_plugins.md Executable file → Normal file
View file

0
docs/vsts.md Executable file → Normal file
View file

0
experiments_plugin_input/__init__.py Executable file → Normal file
View file

0
experiments_plugin_input/r_basicpitch.py Executable file → Normal file
View file

0
experiments_plugin_input/r_color_art.py Executable file → Normal file
View file

49
functions/audio.py Executable file → Normal file
View file

@ -3,17 +3,38 @@
import av
import os
import configparser
from os.path import exists
from tinydb import TinyDB, Query
audioinfo_cache_filepath = './__config/cache_audioinfo.db'
db = TinyDB(audioinfo_cache_filepath)
samplesdb = Query()
def get_audiofile_info(sample_filename):
audio_path = ''
audio_filesize = 0
audio_crc = 0
audio_moddate = 0
audio_duration = 0
audio_duration = 5
audio_timebase = 44100
audio_hz = 44100
if os.path.exists(sample_filename):
db_searchfound = db.search(samplesdb.path == sample_filename)
out_data = {}
out_data['path'] = sample_filename
out_data['file_size'] = 0
out_data['mod_date'] = 0
out_data['dur'] = 1
out_data['crc'] = 0
out_data['audio_timebase'] = 44100
out_data['rate'] = 44100
out_data['dur_sec'] = 1
if db_searchfound != []:
out_data = db_searchfound[0]
elif os.path.exists(sample_filename):
avdata = av.open(sample_filename)
audio_path = sample_filename
audio_filesize = os.path.getsize(sample_filename)
@ -24,13 +45,17 @@ def get_audiofile_info(sample_filename):
audio_hz_b = avdata.streams.audio[0].rate
if audio_hz_b != None: audio_hz = audio_hz_b
out_data = {}
out_data['path'] = audio_path
out_data['file_size'] = audio_filesize
out_data['crc'] = audio_crc
out_data['mod_date'] = audio_moddate
out_data['dur'] = audio_duration
out_data['audio_timebase'] = audio_timebase
out_data['rate'] = audio_hz
out_data['dur_sec'] = (audio_duration/audio_timebase)
if db.search(samplesdb.path == audio_path) == []:
out_db_data = {}
out_db_data['path'] = audio_path
out_db_data['file_size'] = audio_filesize
out_db_data['mod_date'] = audio_moddate
out_db_data['dur'] = audio_duration
out_db_data['crc'] = 0
out_db_data['audio_timebase'] = audio_timebase
out_db_data['rate'] = audio_hz
out_db_data['dur_sec'] = (audio_duration/audio_timebase)
db.insert(out_db_data)
out_data = out_db_data
return out_data

0
functions/audio_wav.py Executable file → Normal file
View file

0
functions/auto.py Executable file → Normal file
View file

0
functions/colors.py Executable file → Normal file
View file

10
functions/core.py Executable file → Normal file
View file

@ -174,8 +174,9 @@ def convert_type_output(extra_json):
if out_type != 'debug':
convproj_j[0] = song_compat.makecompat(convproj_j[0], in_type, in_dawcapabilities, out_dawcapabilities)
if in_type == 'r':
convproj_j[0] = song_compat.makecompat_any(convproj_j[0], in_type, in_dawcapabilities, out_dawcapabilities)
if in_type in ['r', 'm']: convproj_j[0] = song_compat.makecompat_audiostretch(convproj_j[0], in_type, in_dawcapabilities, out_dawcapabilities)
convproj_j[0] = song_compat.makecompat_any(convproj_j[0], in_type, in_dawcapabilities, out_dawcapabilities)
if in_type == 'ri' and out_type == 'mi': convproj_j[0] = song_convert.ri2mi(convproj_j[0])
if in_type == 'ri' and out_type == 'r': convproj_j[0] = song_convert.ri2r(convproj_j[0])
@ -196,9 +197,8 @@ def convert_type_output(extra_json):
if out_type != 'debug':
convproj_j[0] = song_compat.makecompat(convproj_j[0], out_type, in_dawcapabilities, out_dawcapabilities)
if in_type != 'r':
convproj_j[0] = song_compat.makecompat_any(convproj_j[0], out_type, in_dawcapabilities, out_dawcapabilities)
if out_type in ['r', 'm']: convproj_j[0] = song_compat.makecompat_audiostretch(convproj_j[0], out_type, in_dawcapabilities, out_dawcapabilities)
convproj_j[1] = currentplug_output[3]
convproj_j[2] = currentplug_output[4]

0
functions/data_bytes.py Executable file → Normal file
View file

58
functions/data_values.py Executable file → Normal file
View file

@ -61,4 +61,60 @@ def sort_pos(datapart):
def list_chunks(i_list, i_amount):
return [i_list[i:i + i_amount] for i in range(0, len(i_list), i_amount)]
return [i_list[i:i + i_amount] for i in range(0, len(i_list), i_amount)]
def tempo_to_rate(i_in, i_mode):
if i_mode == True: return (120/i_in)
if i_mode == False: return (i_in/120)
def time_from_steps(i_dict, i_name, i_stretched, i_value, i_rate):
in_bpm = 1
in_stretch = 1
if i_rate != None: in_stretch = i_rate
if i_stretched == False:
out_nonstretch = i_value
out_normal = i_value*in_stretch
i_dict[i_name+'_nonstretch'] = out_nonstretch
i_dict[i_name] = out_normal
else:
out_nonstretch = i_value/in_stretch
out_normal = i_value
i_dict[i_name+'_nonstretch'] = i_value/in_stretch
i_dict[i_name] = i_value
out_real_nonstretch = (out_nonstretch/8)*in_bpm
out_real = out_real_nonstretch/in_stretch
i_dict[i_name+'_real_nonstretch'] = out_real_nonstretch
i_dict[i_name+'_real'] = out_real
def time_from_seconds(i_dict, i_name, i_stretched, i_value, i_rate):
in_bpm = 1
in_stretch = 1
if i_rate != None: in_stretch = i_rate
if i_stretched == False:
out_real_nonstretch = i_value
out_real = out_real_nonstretch/in_stretch
i_dict[i_name+'_real_nonstretch'] = out_real_nonstretch
i_dict[i_name+'_real'] = out_real
else:
out_real = i_value
out_real_nonstretch = out_real*in_stretch
i_dict[i_name+'_real_nonstretch'] = out_real_nonstretch
i_dict[i_name+'_real'] = out_real
out_nonstretch = (out_real_nonstretch*8)*in_bpm
out_normal = out_nonstretch*in_stretch
i_dict[i_name+'_nonstretch'] = out_nonstretch
i_dict[i_name] = out_normal

0
functions/folder_samples.py Executable file → Normal file
View file

0
functions/format_caustic.py Executable file → Normal file
View file

View file

@ -23,9 +23,14 @@ def calctempotimed(i_value):
#print('VALUE', str(i_value).ljust(20), '| MUL', str(i_tempomul).ljust(20), '| OUT', str(i_out).ljust(20))
return i_out
def decodetext(event_data):
return event_data.decode('utf-16le').rstrip('\x00\x00')
# ------------- parse -------------
def parse_arrangement(arrdata):
#print(FLSplitted)
bio_fldata = create_bytesio(arrdata)
output = []
while bio_fldata[0].tell() < bio_fldata[1]:
@ -38,34 +43,26 @@ def parse_arrangement(arrdata):
placement['trackindex'] = int.from_bytes(bio_fldata[0].read(4), "little")
placement['unknown1'] = int.from_bytes(bio_fldata[0].read(2), "little")
placement['flags'] = int.from_bytes(bio_fldata[0].read(2), "little")
placement['unknown2'] = int.from_bytes(bio_fldata[0].read(2), "little")
placement['unknown3'] = int.from_bytes(bio_fldata[0].read(2), "little")
if FLSplitted[0] == '21':
placement['unknown4'] = bio_fldata[0].read(28)
placement['unknown2'] = int.from_bytes(bio_fldata[0].read(4), "little")
startoffset_bytes = bio_fldata[0].read(4)
endoffset_bytes = bio_fldata[0].read(4)
if FLSplitted[0] == '21':
startoffset_bytes = placement['unknown4'][0:4]
endoffset_bytes = placement['unknown4'][4:8]
placement['unknown3'] = bio_fldata[0].read(28)
startoffset = int.from_bytes(startoffset_bytes, "little")
endoffset = int.from_bytes(endoffset_bytes, "little")
startoffset_float = struct.unpack('<f', startoffset_bytes)[0]
endoffset_float = struct.unpack('<f', endoffset_bytes)[0]
if FLSplitted[0] == '21':
if placement['itemindex'] > placement['patternbase']:
if startoffset != 4294967295 and startoffset != 3212836864: placement['startoffset'] = startoffset
if endoffset != 4294967295 and endoffset != 3212836864: placement['endoffset'] = endoffset
if placement['itemindex'] > placement['patternbase']:
if startoffset != 4294967295 and startoffset != 3212836864: placement['startoffset'] = startoffset
if endoffset != 4294967295 and endoffset != 3212836864: placement['endoffset'] = endoffset
else:
if placement['itemindex'] > placement['patternbase']:
if startoffset != 4294967295 and startoffset != 3212836864: placement['startoffset'] = startoffset
if endoffset != 4294967295 and endoffset != 3212836864: placement['endoffset'] = endoffset
else:
if startoffset_float > 0: placement['startoffset'] = calctempotimed(startoffset_float)
if endoffset_float > 0: placement['endoffset'] = calctempotimed(endoffset_float)
#print(placement['length'], startoffset_float, endoffset_float)
if startoffset_float > 0: placement['startoffset'] = calctempotimed(startoffset_float)
if endoffset_float > 0: placement['endoffset'] = calctempotimed(endoffset_float)
output.append(placement)
return output
@ -175,6 +172,7 @@ def parse_flevent(datastream):
def parse(inputfile):
global FL_Main
global FLSplitted
fileobject = open(inputfile, 'rb')
headername = fileobject.read(4)
rifftable = data_bytes.riff_read(fileobject, 0)
@ -221,6 +219,10 @@ def parse(inputfile):
FL_FXCreationMode = 0
FL_TimeMarkers = {}
FL_ChanGroupName = []
T_FL_CurrentArrangement = '0'
FL_Arrangements[T_FL_CurrentArrangement] = {}
FL_Arrangements[T_FL_CurrentArrangement]['tracks'] = {}
FL_Arrangements[T_FL_CurrentArrangement]['items'] = {}
T_FL_FXNum = -1
for event in eventtable:
@ -230,7 +232,7 @@ def parse(inputfile):
if event_id == 199:
FLVersion = event_data.decode('utf-8').rstrip('\x00')
FLSplitted = FLVersion.split('.')
if int(FLSplitted[0]) < 20:
if int(FLSplitted[0]) < 12:
print('[error] FL version '+FLSplitted[0]+' is not supported.')
exit()
FL_Main['Version'] = FLVersion
@ -239,15 +241,15 @@ def parse(inputfile):
if event_id == 17: FL_Main['Numerator'] = event_data
if event_id == 18: FL_Main['Denominator'] = event_data
if event_id == 11: FL_Main['Shuffle'] = event_data
if event_id == 194: FL_Main['Title'] = event_data.decode('utf-16le').rstrip('\x00\x00')
if event_id == 206: FL_Main['Genre'] = event_data.decode('utf-16le').rstrip('\x00\x00')
if event_id == 207: FL_Main['Author'] = event_data.decode('utf-16le').rstrip('\x00\x00')
if event_id == 202: FL_Main['ProjectDataPath'] = event_data.decode('utf-16le').rstrip('\x00\x00')
if event_id == 195: FL_Main['Comment'] = event_data.decode('utf-16le').rstrip('\x00\x00')
if event_id == 197: FL_Main['URL'] = event_data.decode('utf-16le').rstrip('\x00\x00')
if event_id == 194: FL_Main['Title'] = decodetext(event_data)
if event_id == 206: FL_Main['Genre'] = decodetext(event_data)
if event_id == 207: FL_Main['Author'] = decodetext(event_data)
if event_id == 202: FL_Main['ProjectDataPath'] = decodetext(event_data)
if event_id == 195: FL_Main['Comment'] = decodetext(event_data)
if event_id == 197: FL_Main['URL'] = decodetext(event_data)
if event_id == 237: FL_Main['ProjectTime'] = event_data
if event_id == 10: FL_Main['ShowInfo'] = event_data
if event_id == 231: FL_ChanGroupName.append(event_data.decode('utf-16le').rstrip('\x00\x00'))
if event_id == 231: FL_ChanGroupName.append(decodetext(event_data))
if event_id == 65:
T_FL_CurrentPattern = event_data
@ -296,7 +298,7 @@ def parse(inputfile):
if event_data != 5328737:
FL_Patterns[str(T_FL_CurrentPattern)]['color'] = event_data
if event_id == 193:
FL_Patterns[str(T_FL_CurrentPattern)]['name'] = event_data.decode('utf-16le').rstrip('\x00\x00')
FL_Patterns[str(T_FL_CurrentPattern)]['name'] = decodetext(event_data)
if event_id == 99:
T_FL_CurrentArrangement = event_data
@ -308,7 +310,7 @@ def parse(inputfile):
FL_TimeMarkers = FL_Arrangements[str(T_FL_CurrentArrangement)]['timemarkers']
TimeMarker_id = 0
if event_id == 241:
FL_Arrangements[str(T_FL_CurrentArrangement)]['name'] = event_data.decode('utf-16le').rstrip('\x00\x00')
FL_Arrangements[str(T_FL_CurrentArrangement)]['name'] = decodetext(event_data)
if event_id == 233:
playlistitems = parse_arrangement(event_data)
FL_Arrangements[str(T_FL_CurrentArrangement)]['items'] = playlistitems
@ -322,7 +324,7 @@ def parse(inputfile):
if event_id == 239: #PLTrackName
if str(currenttracknum) not in FL_Tracks:
FL_Tracks[str(currenttracknum)] = {}
FL_Tracks[str(currenttracknum)]['name'] = event_data.decode('utf-16le').rstrip('\x00\x00')
FL_Tracks[str(currenttracknum)]['name'] = decodetext(event_data)
if event_id == 148:
@ -335,7 +337,7 @@ def parse(inputfile):
FL_TimeMarkers[str(T_FL_CurrentTimeMarker)]['type'] = timemarkertype
FL_TimeMarkers[str(T_FL_CurrentTimeMarker)]['pos'] = timemarkertime
if event_id == 205:
event_text = event_data.decode('utf-16le').rstrip('\x00\x00')
event_text = decodetext(event_data)
#print('\\__TimeMarkerName:', event_text)
FL_TimeMarkers[str(T_FL_CurrentTimeMarker)]['name'] = event_text
if event_id == 33:
@ -364,7 +366,7 @@ def parse(inputfile):
T_FL_FXIcon = None
if FL_FXCreationMode == 0:
if event_id == 201:
event_text = event_data.decode('utf-16le').rstrip('\x00\x00')
event_text = decodetext(event_data)
#print('\\__DefPluginName:', event_text)
DefPluginName = event_text
if event_id == 212:
@ -374,7 +376,7 @@ def parse(inputfile):
#print(event_data)
if event_id == 203:
event_text = event_data.decode('utf-16le').rstrip('\x00\x00')
event_text = decodetext(event_data)
#print('\\__PluginName:', event_text)
FL_Channels[str(T_FL_CurrentChannel)]['name'] = event_text
if event_id == 155:
@ -416,7 +418,7 @@ def parse(inputfile):
if event_id == 20: FL_Channels[str(T_FL_CurrentChannel)]['looptype'] = event_data
if event_id == 135: FL_Channels[str(T_FL_CurrentChannel)]['middlenote'] = event_data
if event_id == 196:
samplefilename = event_data.decode('utf-16le').rstrip('\x00\x00')
samplefilename = decodetext(event_data)
if samplefilename[:21] == '%FLStudioFactoryData%':
samplefilename = "C:\\Program Files\\Image-Line\\FL Studio 20" + samplefilename[21:]
FL_Channels[str(T_FL_CurrentChannel)]['samplefilename'] = samplefilename
@ -439,7 +441,7 @@ def parse(inputfile):
T_FL_FXColor = None
T_FL_FXIcon = None
if event_id == 201:
event_text = event_data.decode('utf-16le').rstrip('\x00\x00')
event_text = decodetext(event_data)
#print('\\__DefPluginName:', event_text)
DefPluginName = event_text
if event_id == 212:
@ -449,7 +451,7 @@ def parse(inputfile):
FXPlugin['data'] = event_data
if event_id == 155: FXPlugin['icon'] = event_data
if event_id == 128: FXPlugin['color'] = event_data
if event_id == 203: FXPlugin['name'] = event_data.decode('utf-16le').rstrip('\x00\x00')
if event_id == 203: FXPlugin['name'] = decodetext(event_data)
if event_id == 98: #FXToSlotNum
FL_Mixer[str(T_FL_FXNum)]['slots'][event_data] = FXPlugin
FXPlugin = None
@ -458,7 +460,7 @@ def parse(inputfile):
if event_id == 154: FL_Mixer[str(T_FL_FXNum)]['inchannum'] = event_data
if event_id == 147: FL_Mixer[str(T_FL_FXNum)]['outchannum'] = event_data
if event_id == 204:
event_text = event_data.decode('utf-16le').rstrip('\x00\x00')
event_text = decodetext(event_data)
FL_Mixer[str(T_FL_FXNum+1)]['name'] = event_text
output = {}

4
functions/format_flp_enc.py Executable file → Normal file
View file

@ -57,6 +57,7 @@ def make_arrangement(data_FLdt, arrangements):
BytesIO_arrangement.write(item['unknown2'].to_bytes(2, 'little'))
BytesIO_arrangement.write(item['unknown3'].to_bytes(2, 'little'))
if int(item['itemindex']) > item['patternbase']:
if 'startoffset' in item: BytesIO_arrangement.write(item['startoffset'].to_bytes(4, 'little'))
else: BytesIO_arrangement.write(b'\xff\xff\xff\xff')
@ -69,11 +70,12 @@ def make_arrangement(data_FLdt, arrangements):
if 'startoffset' in item: startoffset_out = calctempotimed(item['startoffset'])
if 'endoffset' in item: endoffset_out = calctempotimed(item['endoffset'])
#print(item['length'], startoffset_out, endoffset_out)
BytesIO_arrangement.write(struct.pack('<f', startoffset_out))
BytesIO_arrangement.write(struct.pack('<f', endoffset_out))
BytesIO_arrangement.seek(0)
make_flevent(data_FLdt, 36, 0)
make_flevent(data_FLdt, 233, BytesIO_arrangement.read()) #PlayListItems

0
functions/format_midi_in.py Executable file → Normal file
View file

0
functions/format_midi_out.py Executable file → Normal file
View file

0
functions/idvals.py Executable file → Normal file
View file

0
functions/list_vst.py Executable file → Normal file
View file

0
functions/midi_exdata.py Executable file → Normal file
View file

0
functions/note_convert.py Executable file → Normal file
View file

0
functions/note_data.py Executable file → Normal file
View file

0
functions/note_mod.py Executable file → Normal file
View file

0
functions/notelist_data.py Executable file → Normal file
View file

0
functions/params_vst.py Executable file → Normal file
View file

39
functions/placement_data.py Executable file → Normal file
View file

@ -19,42 +19,3 @@ def makepl_n_mi(t_pos, t_dur, t_fromindex):
def nl2pl(cvpj_notelist):
return [{'position': 0, 'duration': notelist_data.getduration(cvpj_notelist), 'notelist': cvpj_notelist}]
def time_from_steps(i_dict, i_name, i_stretched, i_value, i_bpm, i_rate):
in_bpm = 120
in_stretch = 1
if i_bpm != None: in_bpm = i_bpm
if i_rate != None: in_stretch = i_rate
tempomul = (120/in_bpm)
if i_stretched == False:
i_dict[i_name+'_nonstretch'] = i_value
i_dict[i_name] = i_value*i_rate
i_dict[i_name+'_real_nonstretch'] = (i_value/8)*tempomul
i_dict[i_name+'_real'] = ((i_value/8)*tempomul)/i_rate
else:
i_dict[i_name+'_nonstretch'] = i_value/i_rate
i_dict[i_name] = i_value
i_dict[i_name+'_real_nonstretch'] = ((i_value*tempomul)/8)/i_rate
i_dict[i_name+'_real'] = (((i_value*tempomul)/8)/i_rate)/i_rate
def time_from_seconds(i_dict, i_name, i_stretched, i_value, i_bpm, i_rate):
in_bpm = 120
in_stretch = 1
if i_bpm != None: in_bpm = i_bpm
if i_rate != None: in_stretch = i_rate
str_i_value = i_value/(120/in_bpm)
if i_stretched == False:
i_dict[i_name+'_nonstretch'] = str_i_value*8
i_dict[i_name] = (str_i_value*8)*i_rate
i_dict[i_name+'_real_nonstretch'] = i_value
i_dict[i_name+'_real'] = i_value/i_rate
else:
i_dict[i_name+'_nonstretch'] = (str_i_value*i_rate)*8
i_dict[i_name] = ((str_i_value*i_rate)*8)*i_rate
i_dict[i_name+'_real_nonstretch'] = i_value*i_rate
i_dict[i_name+'_real'] = i_value

0
functions/placements.py Executable file → Normal file
View file

0
functions/plug_conv.py Executable file → Normal file
View file

0
functions/plugin_vst2.py Executable file → Normal file
View file

0
functions/song.py Executable file → Normal file
View file

235
functions/song_compat.py Executable file → Normal file
View file

@ -6,16 +6,13 @@ from functions import notelist_data
from functions import data_values
from functions import xtramath
from functions import tracks
from functions import placement_data
from functions import data_values
from functions import audio
import json
import math
# -------------------------------------------- fxrack --------------------------------------------
def list2fxrack(cvpj_l, input_list, fxnum, defualtname, starttext):
if 'name' in input_list: fx_name = starttext+input_list['name']
else: fx_name = starttext+defualtname
@ -251,7 +248,6 @@ def r_addloops(projJ):
else: print('unchanged')
def r_removeloops_cutpoint(pl_pos, pl_dur, cut_start, cut_end):
return [pl_pos, pl_dur, cut_start, cut_end]
@ -297,19 +293,11 @@ def r_removeloops_after_loop(bl_p_pos, bl_p_dur, bl_p_start, bl_l_start, bl_l_en
return cutpoints
def r_removeloops_placements(cvpj_placements, tempo):
def r_removeloops_placements(cvpj_placements, tempo, isaudio):
tempomul = data_values.tempo_to_rate(tempo, False)
new_placements = []
for cvpj_placement in cvpj_placements:
audiorate = 1
if 'audiomod' in cvpj_placement:
if 'stretch' in cvpj_placement['audiomod']:
stretchdata = cvpj_placement['audiomod']['stretch']
if 'enabled' in stretchdata:
if stretchdata['enabled'] == True:
if 'time' in stretchdata:
if 'data' in stretchdata['time']:
if 'rate' in stretchdata['time']['data']:
audiorate = stretchdata['time']['data']['rate']
if 'cut' in cvpj_placement:
if cvpj_placement['cut']['type'] == 'loop':
@ -333,8 +321,20 @@ def r_removeloops_placements(cvpj_placements, tempo):
cvpj_placement_cutted['duration'] = cutpoint[1]
cvpj_placement_cutted['cut'] = {}
cvpj_placement_cutted['cut']['type'] = 'cut'
placement_data.time_from_steps(cvpj_placement_cutted['cut'], 'start', True, cutpoint[2], tempo, audiorate)
placement_data.time_from_steps(cvpj_placement_cutted['cut'], 'end', True, cutpoint[3], tempo, audiorate)
if isaudio == False:
cvpj_placement_cutted['cut']['start'] = cutpoint[2]
cvpj_placement_cutted['cut']['end'] = cutpoint[3]
else:
audiorate = 1
if 'audiomod' in cvpj_placement:
audiomoddata = cvpj_placement['audiomod']
if 'stretch_method' in audiomoddata:
if audiomoddata['stretch_method'] == 'rate_ignoretempo':
audiorate = 1/audiomoddata['stretch_data']['rate']
data_values.time_from_steps(cvpj_placement_cutted['cut'], 'start', True, cutpoint[2]*tempomul, audiorate)
data_values.time_from_steps(cvpj_placement_cutted['cut'], 'end', True, cutpoint[3]*tempomul, audiorate)
new_placements.append(cvpj_placement_cutted)
else: new_placements.append(cvpj_placement)
@ -358,21 +358,175 @@ def r_removeloops(projJ):
for t_lanedata in s_lanedata:
tj_lanedata = s_lanedata[t_lanedata]
if 'notes' in tj_lanedata:
track_placements_data['notes'] = r_removeloops_placements(tj_lanedata['notes'], tempo)
track_placements_data['notes'] = r_removeloops_placements(tj_lanedata['notes'], tempo, False)
if 'audio' in tj_lanedata:
track_placements_data['audio'] = r_removeloops_placements(tj_lanedata['audio'], tempo, True)
if not_laned == True:
print('[compat] RemoveLoops: non-laned: '+track_placements_id)
if 'notes' in track_placements_data:
track_placements_data['notes'] = r_removeloops_placements(track_placements_data['notes'], tempo)
track_placements_data['notes'] = r_removeloops_placements(track_placements_data['notes'], tempo, False)
if 'audio' in track_placements_data:
track_placements_data['audio'] = r_removeloops_placements(track_placements_data['audio'], tempo)
track_placements_data['audio'] = r_removeloops_placements(track_placements_data['audio'], tempo, True)
def m_removeloops(projJ):
tempo = projJ['bpm']
for playlist_id in projJ['playlist']:
playlist_id_data = projJ['playlist'][playlist_id]
if 'placements_notes' in playlist_id_data:
playlist_id_data['placements_notes'] = r_removeloops_placements(playlist_id_data['placements_notes'], tempo)
playlist_id_data['placements_notes'] = r_removeloops_placements(playlist_id_data['placements_notes'], tempo, False)
# -------------------------------------------- placement_audio_stretch --------------------------------------------
def warp2rate(cvpj_placements, tempo):
new_placements = []
tempomul = (120/tempo)
for cvpj_placement in cvpj_placements:
audiorate = 1
minus_offset = 0
plus_offset = 0
if 'audiomod' in cvpj_placement:
old_audiomod = cvpj_placement['audiomod']
new_audiomod = {}
new_audiomod['stretch_data'] = {}
new_audiomod['stretch_method'] = None
new_audiomod['stretch_algorithm'] = 'stretch'
if 'pitch' in old_audiomod: new_audiomod['pitch'] = old_audiomod['pitch']
if 'stretch_method' in old_audiomod:
if old_audiomod['stretch_method'] == 'warp':
t_warpmarkers = old_audiomod['stretch_data']
if t_warpmarkers[0]['pos'] != 0:
minuswarppos = t_warpmarkers[0]['pos']
if t_warpmarkers[0]['pos'] < 0: minus_offset -= minuswarppos
if t_warpmarkers[0]['pos'] > 0: plus_offset += minuswarppos
for t_warpmarker in t_warpmarkers:
t_warpmarker['pos'] -= minuswarppos
#print(minus_offset, plus_offset)
audio_info = audio.get_audiofile_info(cvpj_placement['file'])
audio_dur_sec_steps = audio_info['dur_sec']*8
if 'stretch_algorithm' in old_audiomod: new_audiomod['stretch_algorithm'] = old_audiomod['stretch_algorithm']
if len(t_warpmarkers) >= 2:
t_warpmarker_last = t_warpmarkers[-1]
new_audiomod['stretch_method'] = 'rate_ignoretempo'
audiorate = (1/((t_warpmarker_last['pos']/8)/t_warpmarkers[-1]['pos_real']))
new_audiomod['stretch_data']['rate'] = audiorate
cvpj_placement['audiomod'] = new_audiomod
if 'cut' in cvpj_placement:
cutdata = cvpj_placement['cut']
if audiorate != 1:
if cutdata['type'] == 'loop':
data_values.time_from_steps(cutdata, 'start', True, cutdata['start']+minus_offset, audiorate)
data_values.time_from_steps(cutdata, 'loopstart', True, cutdata['loopstart']+minus_offset, audiorate)
data_values.time_from_steps(cutdata, 'loopend', True, cutdata['loopend']+minus_offset, audiorate )
cvpj_placement['position'] += plus_offset
cvpj_placement['duration'] -= plus_offset
cvpj_placement['duration'] += minus_offset
if cutdata['type'] == 'cut':
data_values.time_from_steps(cutdata, 'start', True, cutdata['start']+minus_offset, (1/audiorate)*tempomul )
data_values.time_from_steps(cutdata, 'end', True, cutdata['end']+minus_offset-plus_offset, (1/audiorate)*tempomul )
return cvpj_placements
def rate2warp(cvpj_placements, tempo):
new_placements = []
tempomul = (120/tempo)
for cvpj_placement in cvpj_placements:
audiorate = 1
ratetempo = 1
if 'audiomod' in cvpj_placement:
old_audiomod = cvpj_placement['audiomod']
new_audiomod = {}
if 'stretch_method' in old_audiomod:
if old_audiomod['stretch_method'] == 'rate_ignoretempo':
audio_info = audio.get_audiofile_info(cvpj_placement['file'])
audio_dur_sec = audio_info['dur_sec']
t_stretch_data = old_audiomod['stretch_data']
new_audiomod = {}
new_audiomod['stretch_method'] = 'warp'
new_audiomod['stretch_algorithm'] = 'stretch'
if 'stretch_algorithm' in old_audiomod: new_audiomod['stretch_algorithm'] = old_audiomod['stretch_algorithm']
if 'pitch' in old_audiomod: new_audiomod['pitch'] = old_audiomod['pitch']
audiorate = t_stretch_data['rate']
ratetempo = 1/(audiorate/tempomul)
#for value in [audiorate, tempomul, audiorate/tempomul]:
# print(str(value).ljust(20), end=' ')
#print()
new_audiomod['stretch_data'] = [
{'pos': 0.0, 'pos_real': 0.0},
{'pos': audio_dur_sec*8, 'pos_real': (audio_dur_sec*audiorate)}
]
cvpj_placement['audiomod'] = new_audiomod
if 'cut' in cvpj_placement:
cutdata = cvpj_placement['cut']
if cutdata['type'] == 'cut':
if 'start' not in cutdata: data_values.time_from_steps(cutdata, 'start', True, 0, audiorate)
data_values.time_from_seconds(cutdata, 'start', False, cutdata['start_real_nonstretch']*ratetempo, 1)
data_values.time_from_seconds(cutdata, 'end', False, cutdata['end_real_nonstretch']*ratetempo, 1)
return cvpj_placements
def r_changestretch(projJ, stretchtype):
tempo = projJ['bpm']
if 'track_placements' in projJ:
for track_placements_id in projJ['track_placements']:
track_placements_data = projJ['track_placements'][track_placements_id]
not_laned = True
if 'laned' in track_placements_data:
print('[compat] warp2rate: laned: '+track_placements_id)
if s_pldata['laned'] == 1:
not_laned = False
s_lanedata = s_pldata['lanedata']
s_laneordering = s_pldata['laneorder']
for t_lanedata in s_lanedata:
tj_lanedata = s_lanedata[t_lanedata]
if 'audio' in tj_lanedata:
if stretchtype == 'rate':
print('[compat] warp2rate: laned: '+track_placements_id)
tj_lanedata['audio'] = warp2rate(tj_lanedata['audio'], tempo)
if stretchtype == 'warp':
print('[compat] rate2warp: laned: '+track_placements_id)
tj_lanedata['audio'] = rate2warp(tj_lanedata['audio'], tempo)
if not_laned == True:
if 'audio' in track_placements_data:
if stretchtype == 'rate':
print('[compat] warp2rate: non-laned: '+track_placements_id)
track_placements_data['audio'] = warp2rate(track_placements_data['audio'], tempo)
if stretchtype == 'warp':
print('[compat] rate2warp: non-laned: '+track_placements_id)
track_placements_data['audio'] = rate2warp(track_placements_data['audio'], tempo)
def m_changestretch(projJ, stretchtype):
tempo = projJ['bpm']
for playlist_id in projJ['playlist']:
playlist_id_data = projJ['playlist'][playlist_id]
if 'placements_audio' in playlist_id_data:
if stretchtype == 'rate': playlist_id_data['placements_audio'] = warp2rate(playlist_id_data['placements_audio'], tempo)
if stretchtype == 'warp': playlist_id_data['placements_audio'] = rate2warp(playlist_id_data['placements_audio'], tempo)
# -------------------------------------------- track_lanes --------------------------------------------
@ -605,6 +759,28 @@ def beats_to_seconds(cvpj_l):
# -------------------------------------------- Main --------------------------------------------
audiostretch_processed = False
def makecompat_audiostretch(cvpj_l, cvpj_type, in_dawcapabilities, out_dawcapabilities):
cvpj_proj = json.loads(cvpj_l)
global audiostretch_processed
if audiostretch_processed == False and cvpj_type in ['r', 'm']:
in__placement_audio_stretch = []
out__placement_audio_stretch = []
if 'placement_audio_stretch' in in_dawcapabilities: in__placement_audio_stretch = in_dawcapabilities['placement_audio_stretch']
if 'placement_audio_stretch' in out_dawcapabilities: out__placement_audio_stretch = out_dawcapabilities['placement_audio_stretch']
if 'warp' in in__placement_audio_stretch and 'warp' not in out__placement_audio_stretch:
if cvpj_type == 'm': m_changestretch(cvpj_proj, 'rate')
if cvpj_type == 'r': r_changestretch(cvpj_proj, 'rate')
audiostretch_processed = True
if 'rate' in in__placement_audio_stretch and 'warp' in out__placement_audio_stretch:
if cvpj_type == 'm': m_changestretch(cvpj_proj, 'warp')
if cvpj_type == 'r': r_changestretch(cvpj_proj, 'warp')
audiostretch_processed = True
return json.dumps(cvpj_proj)
def makecompat_any(cvpj_l, cvpj_type, in_dawcapabilities, out_dawcapabilities):
cvpj_proj = json.loads(cvpj_l)
@ -623,13 +799,14 @@ def makecompat_any(cvpj_l, cvpj_type, in_dawcapabilities, out_dawcapabilities):
if 'time_seconds' in in_dawcapabilities: in__time_seconds = in_dawcapabilities['time_seconds']
if 'time_seconds' in out_dawcapabilities: out__time_seconds = out_dawcapabilities['time_seconds']
print('[compat] '+str(in__fxrack).ljust(5)+' | '+str(out__fxrack).ljust(5)+' | fxrack')
print('[compat] '+str(in__auto_nopl).ljust(5)+' | '+str(out__auto_nopl).ljust(5)+' | auto_nopl')
print('[compat] '+str(in__fxrack).ljust(5)+' | '+str(out__fxrack).ljust(5)+' | fxrack')
print('[compat] '+str(in__time_seconds).ljust(5)+' | '+str(out__time_seconds).ljust(5)+' | time_seconds')
if in__fxrack == False and out__fxrack == True: trackfx2fxrack(cvpj_proj, cvpj_type)
if in__auto_nopl == False and out__auto_nopl == True: remove_auto_placements(cvpj_proj)
if in__time_seconds == False and out__time_seconds == True: beats_to_seconds(cvpj_proj)
return json.dumps(cvpj_proj)
r_processed = False
@ -673,16 +850,16 @@ def makecompat(cvpj_l, cvpj_type, in_dawcapabilities, out_dawcapabilities):
if 'placement_audio_events' in out_dawcapabilities: out__placement_audio_events = out_dawcapabilities['placement_audio_events']
if isprinted == False:
print('[compat] '+str(in__track_lanes).ljust(5)+' | '+str(out__track_lanes).ljust(5)+' | track_lanes')
print('[compat] '+str(in__placement_audio_events).ljust(5)+' | '+str(out__placement_audio_events).ljust(5)+' | placement_audio_events')
print('[compat] '+str(in__placement_cut).ljust(5)+' | '+str(out__placement_cut).ljust(5)+' | placement_cut')
print('[compat] '+str(in__placement_loop).ljust(5)+' | '+str(out__placement_loop).ljust(5)+' | placement_loop')
print('[compat] '+str(in__track_lanes).ljust(5)+' | '+str(out__track_lanes).ljust(5)+' | track_lanes')
print('[compat] '+str(in__track_nopl).ljust(5)+' | '+str(out__track_nopl).ljust(5)+' | track_nopl')
print('[compat] '+str(in__placement_audio_events).ljust(5)+' | '+str(out__placement_audio_events).ljust(5)+' | placement_audio_events')
isprinted = True
if cvpj_type == 'm' and m_processed == False:
if in__placement_loop == True and out__placement_loop == False: m_removeloops(cvpj_proj)
m_processed = True
#if cvpj_type == 'm' and m_processed == False:
# if in__placement_loop == False and out__placement_loop == True: r_addloops(cvpj_proj)
# m_processed = True
if cvpj_type == 'mi' and mi_processed == False:
if in__placement_loop == True and out__placement_loop == False: m_removeloops(cvpj_proj)

4
functions/song_convert.py Executable file → Normal file
View file

@ -474,6 +474,7 @@ def m2mi_checkdup(cvpj_notelistindex, nledata):
return None
m2mi_sample_names = ['file', 'name', 'color', 'audiomod', 'vol', 'pan', 'fxrack_channel']
m2mi_notes_names = ['notelist', 'name', 'color']
def m2mi(song):
print('[song-convert] Converting from Multiple > MultipleIndexed')
@ -495,9 +496,12 @@ def m2mi(song):
if checksamenl != None: cvpj_placement['fromindex'] = checksamenl
else:
cvpj_notelistindex['m2mi_' + str(pattern_number)] = temp_nle
if 'color' in cvpj_placement: temp_nle['color'] = cvpj_placement['color']
if 'name' in cvpj_placement: temp_nle['name'] = cvpj_placement['name']
cvpj_placement['fromindex'] = 'm2mi_' + str(pattern_number)
del cvpj_placement['notelist']
pattern_number += 1
cvpj_proj['notelistindex'] = cvpj_notelistindex
sample_number = 1

0
functions/song_tracker.py Executable file → Normal file
View file

0
functions/tracks.py Executable file → Normal file
View file

0
functions/xtramath.py Executable file → Normal file
View file

0
functions_plugconv/input_audiosauna.py Executable file → Normal file
View file

0
functions_plugconv/input_flstudio.py Executable file → Normal file
View file

0
functions_plugconv/input_flstudio_wrapper.py Executable file → Normal file
View file

0
functions_plugconv/input_jummbox.py Executable file → Normal file
View file

0
functions_plugconv/input_pxtone.py Executable file → Normal file
View file

0
functions_plugconv/input_soundchip.py Executable file → Normal file
View file

0
functions_plugconv/output_audiosauna_vst2.py Executable file → Normal file
View file

0
functions_plugconv/output_flstudio_vst2.py Executable file → Normal file
View file

0
functions_plugconv/output_lmms_vst2.py Executable file → Normal file
View file

0
functions_plugconv/output_multisampler_vst2.py Executable file → Normal file
View file