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.

414 lines
7.9 KiB

// .scl to sunvox set pitch (sp) converter
// by acheney
// under mit license
// NOTE: BE SURE THERE ARE NO DUPLICATE LINE ENDINGS IN YOUR .SCL FILE, OR ELSE THE SCRIPT WILL FAIL!
// .scl files generated using sevish's scale workshop should work fine, as well as .scl files saved locally on your system
// but if you download an .scl file from anywhere else, be sure to convert the line endings to those of your os
// on linux/osx you can use dos2unix, and on windows unix2dos, or for both, any text editor that lets you convert line endings
// - BEGIN CONFIG -
// the frequency of the tuning center in hertz
tuning_center_freq = 440
// the midi note to use as the tuning center. 57 = A4
tuning_center_midi = 57
// - END CONFIG -
sv = sv_new()
scl_filename = file_dialog( "load .scl file", "scl", "file.scl" )
scl_name = ""
scl_size = 0
scl_list = new( 1024, 1, INT8 )
scl_pitches = new( 120, 1, INT16 )
clean( scl_list, 0 )
clean( scl_pitches, 0 )
scl_read( scl_filename )
logf( "name: %s\n", scl_name )
logf( "size: %d\n", scl_size )
resize( scl_list, scl_size )
if (scl_size > 0 ) {
scl_write( )
sv_set_name( sv, scl_name )
sv_lock( sv )
sv_new_module( sv, "Analog generator", "Preview", 256, 512, 0 )
sv_connect_module( sv, 1, 0 )
pat = sv_new_pattern( sv, -1, 0, 0, 1, 120, 0, scl_name )
sv_unlock( sv )
i = 0 while i < 120
{
sv_lock( sv )
sv_set_pattern_event( sv, pat, 0, i, NOTECMD_SET_PITCH, 00, 02, 0000, scl_pitches[ i ] )
sv_unlock( sv )
i = i + 1
}
scl_name = sanitize( scl_name )
// logf( "sanitized filename: %s\n", scl_name )
strcat( scl_name, ".sunvox" )
if sv_save( sv, scl_name ) == 0 { logf( "file saved!\n" ) }
}
sv_remove( sv )
logf( "\n" )
show_log()
fn scl_read( $scl_filename ) {
$temp_string = new( 1024, 1, INT8 )
$length = 0
$metadata_counter = 0
$list_counter = 0
$is_comment = 0
logf( "file to load: %s\n", $scl_filename )
$scl_file = fopen( $scl_filename, "r" )
if $scl_file == 0 { ret( -1 ) }
while 1 {
$length = fgets( $temp_string, 2048, $scl_file )
if ( $length == -1 ) {
break
}
if ( $length >= 0 ) {
// logf( "read string: %s\n", $temp_string )
if ( $temp_string[ 0 ] == '!' ) {
$is_comment = 1
} else {
$is_comment = 0
}
if ( $is_comment == 0 ) {
if ( $metadata_counter >= 2 ) {
scl_list[ $list_counter ] = strip_character( $temp_string, ' ' )
$list_counter = $list_counter + 1
}
if ( $metadata_counter == 1 ) {
$metadata_counter = 2
if ($length == 0) {
logf("ERROR: no size specified\n")
breakall
} else {
// logf( "number conversion: %d\n", str_to_num( strip_character( $temp_string, ' ' ) ) )
scl_size = str_to_num( strip_character( $temp_string, ' ' ) )
}
}
if ( $metadata_counter == 0 ) {
$metadata_counter = 1
if ($length == 0) {
logf("WARNING: no name found. defaulting to filename...\n")
strcat( scl_name, basename( $scl_filename, 0 ) )
} else {
strcat( scl_name, $temp_string )
}
}
} else {
// logf( "comment found, skipping...\n" )
}
}
}
remove( $temp_string )
fclose( $scl_file )
}
fn strip_character( $input, $c ) {
$non_char_count = 0
$dest = clone( $input )
$i = 0 while $i < get_xsize( $input ) + 1 {
if ( $input[ $i ] != $c ) {
$dest[ $non_char_count ] = $input[ $i ]
$non_char_count = $non_char_count + 1
}
$i = $i + 1
}
ret( $dest )
}
fn scl_write( ) {
scl_multipliers = new( scl_size, 1, FLOAT )
current_midi = 0
multiplier_power = 1
i = 0 while i < get_xsize( scl_list ) {
scl_multiplier = 0
current_midi = 0
if ( strstr( scl_list[ i ], "." ) != -1 ) {
scl_multiplier = pow( 2, ( ( str_to_num( scl_list[ i ] ) / 100 ) / 12 ) )
} else {
numerator = new( 256, 1, INT8 )
clean( numerator, 0 )
denominator = new( 256, 1, INT8 )
clean ( denominator, 0 )
slash_offset = 0
no_denominator = 0
j = 0 while 1 {
if ( scl_list[ i ][ j ] == '/' || scl_list[ i ][ j ] == '\\' ) {
break
}
if ( scl_list[ i ][ j ] == ' ' || scl_list[ i ][ j ] == 0 ) {
no_denominator = 1
break
}
numerator[ j ] = scl_list[ i ][ j ]
j = j + 1
slash_offset = slash_offset + 1
}
if ( no_denominator == 0 ) {
j = 0 while 1 {
if ( scl_list[ i ][ j + slash_offset + 1 ] == 0 || scl_list[ i ][ j + slash_offset + 1 ] == ' ' ) {
break;
}
denominator[ j ] = scl_list[ i ][ j + slash_offset + 1 ]
j = j + 1
}
} else {
denominator[ 0 ] = '1'
}
scl_multiplier = str_to_num( numerator ) / str_to_num( denominator )
}
scl_multipliers[ i ] = scl_multiplier
// logf( "multiplier written to %d: %f\n", i, scl_multipliers[ i ] )
i = i + 1
}
i = 0 while i < get_xsize( scl_multipliers ) {
i = i + 1
}
i = 0 while i < 120 {
multiplier_power = floor( ( i - tuning_center_midi ) / scl_size )
// logf( "multiplier power: %d\n", multiplier_power )
center_offset = pow( scl_multipliers[ scl_size - 1 ], multiplier_power )
// logf( "center offset: %d\n", center_offset )
if ( i < tuning_center_midi ) {
scl_pitches[ i ] = freq_to_sp( tuning_center_freq * scl_multipliers[ ( ( ( i - tuning_center_midi ) % scl_size ) - 1 ) + scl_size ] * center_offset )
}
if ( i > tuning_center_midi ) {
scl_pitches[ i ] = freq_to_sp( tuning_center_freq * scl_multipliers[ ( i - tuning_center_midi ) % ( scl_size ) - 1 ] * center_offset )
}
if ( ( tuning_center_midi - i ) % scl_size == 0 ) {
scl_pitches[ i ] = freq_to_sp( tuning_center_freq * center_offset )
}
// logf( "pitch written to %d: %d\n", i, scl_pitches[ i ] )
i = i + 1
}
}
fn freq_to_sp( $freq ) {
ret( 30720 - log2( $freq / 16.3339 ) * 3072 )
}
fn sanitize( $input )
{
$output = clone( $input )
i = 0 while i < get_xsize( $input ) {
if $input[ i ] == '/' { $output[ i ] = '_' }
if $input[ i ] == '\\' { $output[ i ] = '_' }
if $input[ i ] == '\'' { $output[ i ] = '_' }
if $input[ i ] == '\"' { $output[ i ] = '_' }
if $input[ i ] == '\ ' { $output[ i ] = '_' }
if $input[ i ] == ':' { $output[ i ] = '_' }
if $input[ i ] == ',' { $output[ i ] = '_' }
if $input[ i ] == '.' { $output[ i ] = '_' }
i = i + 1
}
ret( $output )
}
fn strrchr( $s, $c )
{
$i = 0
$k = 0
for( $i = strlen( $s ); $i >= 0; $i - 1 )
{
if $s[ $i ] == $c {
$k = 1
break
}
}
if $k { ret( $i ) } else { ret( -1 ) }
}
fn basename( $p, $x )
{
$n = ""
strcat( $n, 0, $p, strrchr( $p, '/' ) + 1 )
if $x
{
ret( $n )
} else {
$nnxl = strrchr( $n, '.' )
$nnx = new( $nnxl, 1, INT8 )
$i = 0 while $i < get_size( $nnx )
{
$nnx[ $i ] = $n[ $i ]
$i = $i + 1
}
ret( $nnx )
}
}
fn show_log()
{
$l = get_system_log()
clear()
print( $l, 0, 0, WHITE, CENTER | CENTER )
frame()
remove( $l )
while 1
{
while( get_event() ) { if EVT[ EVT_TYPE ] == EVT_QUIT { halt } }
frame()
}
}