Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/wavesync/audio.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def write_bpm(bpm)
@bpm = bpm
end

#: (String target_path, ?target_sample_rate: Integer?, ?target_file_type: String?, ?target_bit_depth: Integer?, ?padding_seconds: Numeric?) -> bool
#: (String target_path, ?target_sample_rate: Integer?, ?target_file_type: String?, ?target_bit_depth: Integer?, ?padding_seconds: Numeric?) ?{ (String) -> void } -> bool
def transcode(target_path, target_sample_rate: nil, target_file_type: nil, target_bit_depth: nil, padding_seconds: nil)
options = build_transcode_options(target_sample_rate, target_bit_depth, padding_seconds)
ext = target_file_type || @file_ext.delete_prefix('.')
Expand All @@ -95,6 +95,7 @@ def transcode(target_path, target_sample_rate: nil, target_file_type: nil, targe

begin
@audio.transcode(temp_path, options)
yield temp_path if block_given?
FileUtils.install(temp_path, target_path)
true
rescue Errno::ENOENT
Expand Down
7 changes: 4 additions & 3 deletions lib/wavesync/file_converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ module Wavesync
class FileConverter
DURATION_TOLERANCE_SECONDS = 0.5

#: (Audio audio, String source_file_path, PathResolver path_resolver, AudioFormat source_format, AudioFormat target_format, ?padding_seconds: Numeric?) ?{ () -> void } -> bool
def convert(audio, source_file_path, path_resolver, source_format, target_format, padding_seconds: nil, &before_transcode)
#: (Audio audio, String source_file_path, PathResolver path_resolver, AudioFormat source_format, AudioFormat target_format, ?padding_seconds: Numeric?, ?before_transcode: (^() -> void)?) ?{ (String) -> void } -> bool
def convert(audio, source_file_path, path_resolver, source_format, target_format, padding_seconds: nil, before_transcode: nil, &post_transcode)
needs_format_conversion = target_format.file_type || target_format.sample_rate || target_format.bit_depth
return false unless needs_format_conversion || padding_seconds&.positive?

Expand Down Expand Up @@ -34,7 +34,8 @@ def convert(audio, source_file_path, path_resolver, source_format, target_format
audio.transcode(target_path.to_s, target_sample_rate: target_format.sample_rate,
target_file_type: target_format.file_type,
target_bit_depth: target_format.bit_depth || source_format.bit_depth,
padding_seconds: padding_seconds)
padding_seconds: padding_seconds,
&post_transcode)

true
end
Expand Down
77 changes: 49 additions & 28 deletions lib/wavesync/scanner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def sync(target_library_path, device, pad: false)

@audio_files.each_with_index do |file, index|
audio = Audio.new(file)
bpm = audio.bpm

source_format = audio.format
target_format = device.target_format(source_format, file)
Expand All @@ -34,12 +35,12 @@ def sync(target_library_path, device, pad: false)
original_bars = nil #: Integer?
target_bars = nil #: Integer?
if pad && device.bar_multiple
padding_seconds = TrackPadding.compute(audio.duration, audio.bpm, device.bar_multiple)
original_bars, target_bars = TrackPadding.bar_counts(audio.duration, audio.bpm, device.bar_multiple) unless padding_seconds.zero?
padding_seconds = TrackPadding.compute(audio.duration, bpm, device.bar_multiple)
original_bars, target_bars = TrackPadding.bar_counts(audio.duration, bpm, device.bar_multiple) unless padding_seconds.zero?
padding_seconds = nil if padding_seconds.zero?
end

@ui.bpm(audio.bpm, original_bars: original_bars, target_bars: target_bars)
@ui.bpm(bpm, original_bars: original_bars, target_bars: target_bars)
@ui.file_progress(file)

if source_format.file_type == 'wav'
Expand All @@ -55,35 +56,29 @@ def sync(target_library_path, device, pad: false)

if target_format.file_type || target_format.sample_rate || target_format.bit_depth || padding_seconds
converted = @converter.convert(audio, file, path_resolver, source_format, target_format,
padding_seconds: padding_seconds) do
@ui.conversion_progress(source_format, target_format)
padding_seconds: padding_seconds,
before_transcode: -> { @ui.conversion_progress(source_format, target_format) }) do |local_temp_path|
inject_acid_bpm(local_temp_path, bpm, device)
inject_cue_points(local_temp_path, audio, source_format, target_format)
end
target_path = path_resolver.resolve(file, audio, target_file_type: target_format.file_type)
path_resolver.resolve(file, audio, target_file_type: target_format.file_type)
else
copied = copy_file(audio, file, path_resolver)
@ui.copy(source_format)
target_path = path_resolver.resolve(file, audio)
end

bpm = audio.bpm
if (copied || converted) && device.bpm_source == :acid_chunk && bpm && target_path.extname.downcase == '.wav'
Tempfile.create(['wavesync', '.wav']) do |local_temp_file|
local_temp_file.close
AcidChunk.write_bpm(target_path.to_s, local_temp_file.path, bpm)
FileUtils.install(local_temp_file.path, target_path.to_s)
end
end

if converted && source_format.file_type == 'wav' && target_path.extname.downcase == '.wav'
source_cue_points = audio.cue_points
if source_cue_points.any?
rescaled_cue_points = rescale_cue_points(source_cue_points, audio.sample_rate, target_format.sample_rate || audio.sample_rate)
Tempfile.create(['wavesync', '.wav']) do |local_temp_file|
local_temp_file.close
CueChunk.write(target_path.to_s, local_temp_file.path, rescaled_cue_points)
FileUtils.install(local_temp_file.path, target_path.to_s)
if device.bpm_source == :acid_chunk && bpm && File.extname(file).downcase == '.wav'
target_path = path_resolver.resolve(file, audio)
files_to_cleanup = path_resolver.find_files_to_cleanup(target_path, audio)
files_to_cleanup.each { |cleanup_file| FileUtils.rm_f(cleanup_file) }
if target_path.exist?
copied = false
else
target_path.dirname.mkpath
AcidChunk.write_bpm(file, target_path.to_s, bpm)
copied = true
end
else
copied = copy_file(audio, file, path_resolver)
path_resolver.resolve(file, audio)
end
@ui.copy(source_format)
end

if !copied && !converted
Expand Down Expand Up @@ -121,6 +116,32 @@ def copy_file(audio, source_file_path, path_resolver)
end
end

#: (String local_temp_path, (Integer | Float | String)? bpm, Device device) -> void
def inject_acid_bpm(local_temp_path, bpm, device)
return unless device.bpm_source == :acid_chunk && bpm && File.extname(local_temp_path).downcase == '.wav'

bpm_temp_path = "#{local_temp_path}.bpm.tmp"
AcidChunk.write_bpm(local_temp_path, bpm_temp_path, bpm)
FileUtils.mv(bpm_temp_path, local_temp_path)
ensure
FileUtils.rm_f(bpm_temp_path) if bpm_temp_path
end

#: (String local_temp_path, Audio audio, AudioFormat source_format, AudioFormat target_format) -> void
def inject_cue_points(local_temp_path, audio, source_format, target_format)
return unless source_format.file_type == 'wav' && File.extname(local_temp_path).downcase == '.wav'

source_cue_points = audio.cue_points
return unless source_cue_points.any?

rescaled_cue_points = rescale_cue_points(source_cue_points, audio.sample_rate, target_format.sample_rate || audio.sample_rate)
cue_temp_path = "#{local_temp_path}.cue.tmp"
CueChunk.write(local_temp_path, cue_temp_path, rescaled_cue_points)
FileUtils.mv(cue_temp_path, local_temp_path)
ensure
FileUtils.rm_f(cue_temp_path) if cue_temp_path
end

#: (Array[{identifier: Integer, sample_offset: Integer, label: String?}] cue_points_a, Array[{identifier: Integer, sample_offset: Integer, label: String?}] cue_points_b) -> bool
def same_cue_points?(cue_points_a, cue_points_b)
comparable_cue_points(cue_points_a) == comparable_cue_points(cue_points_b)
Expand Down
4 changes: 2 additions & 2 deletions sig/generated/wavesync/audio.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ module Wavesync
# : (String | Integer | Float bpm) -> void
def write_bpm: (String | Integer | Float bpm) -> void

# : (String target_path, ?target_sample_rate: Integer?, ?target_file_type: String?, ?target_bit_depth: Integer?, ?padding_seconds: Numeric?) -> bool
def transcode: (String target_path, ?target_sample_rate: Integer?, ?target_file_type: String?, ?target_bit_depth: Integer?, ?padding_seconds: Numeric?) -> bool
# : (String target_path, ?target_sample_rate: Integer?, ?target_file_type: String?, ?target_bit_depth: Integer?, ?padding_seconds: Numeric?) ?{ (String) -> void } -> bool
def transcode: (String target_path, ?target_sample_rate: Integer?, ?target_file_type: String?, ?target_bit_depth: Integer?, ?padding_seconds: Numeric?) ?{ (String) -> void } -> bool

private

Expand Down
12 changes: 4 additions & 8 deletions sig/generated/wavesync/commands.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ module Wavesync

attr_accessor description(): untyped

def self.new: (?short: untyped, ?long: untyped, ?description: untyped) -> instance
| ({ ?short: untyped, ?long: untyped, ?description: untyped }) -> instance
def self.new: (?untyped short, ?untyped long, ?untyped description) -> instance
| (?short: untyped, ?long: untyped, ?description: untyped) -> instance
end

class Subcommand < Struct[untyped]
attr_accessor usage(): untyped

attr_accessor description(): untyped

def self.new: (?usage: untyped, ?description: untyped) -> instance
| ({ ?usage: untyped, ?description: untyped }) -> instance
def self.new: (?untyped usage, ?untyped description) -> instance
| (?usage: untyped, ?description: untyped) -> instance
end

CONFIG_OPTION: untyped
Expand All @@ -28,11 +28,7 @@ module Wavesync

# : (String path) -> Config
def self.load_config: (String path) -> Config
end
end

module Wavesync
module Commands
ALL: untyped
end
end
4 changes: 2 additions & 2 deletions sig/generated/wavesync/file_converter.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Wavesync
class FileConverter
DURATION_TOLERANCE_SECONDS: ::Float

# : (Audio audio, String source_file_path, PathResolver path_resolver, AudioFormat source_format, AudioFormat target_format, ?padding_seconds: Numeric?) ?{ () -> void } -> bool
def convert: (Audio audio, String source_file_path, PathResolver path_resolver, AudioFormat source_format, AudioFormat target_format, ?padding_seconds: Numeric?) ?{ () -> void } -> bool
# : (Audio audio, String source_file_path, PathResolver path_resolver, AudioFormat source_format, AudioFormat target_format, ?padding_seconds: Numeric?, ?before_transcode: (^() -> void)?) ?{ (String) -> void } -> bool
def convert: (Audio audio, String source_file_path, PathResolver path_resolver, AudioFormat source_format, AudioFormat target_format, ?padding_seconds: Numeric?, ?before_transcode: (^() -> void)?) ?{ (String) -> void } -> bool
end
end
2 changes: 1 addition & 1 deletion sig/generated/wavesync/python_venv.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module Wavesync
module PythonVenv
PYTHON_PATH: ::String
PYTHON_PATH: untyped

# : () -> bool
def self.available?: () -> bool
Expand Down
6 changes: 6 additions & 0 deletions sig/generated/wavesync/scanner.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ module Wavesync
# : (Audio audio, String source_file_path, PathResolver path_resolver) -> bool
def copy_file: (Audio audio, String source_file_path, PathResolver path_resolver) -> bool

# : (String local_temp_path, (Integer | Float | String)? bpm, Device device) -> void
def inject_acid_bpm: (String local_temp_path, (Integer | Float | String)? bpm, Device device) -> void

# : (String local_temp_path, Audio audio, AudioFormat source_format, AudioFormat target_format) -> void
def inject_cue_points: (String local_temp_path, Audio audio, AudioFormat source_format, AudioFormat target_format) -> void

# : (Array[{identifier: Integer, sample_offset: Integer, label: String?}] cue_points_a, Array[{identifier: Integer, sample_offset: Integer, label: String?}] cue_points_b) -> bool
def same_cue_points?: (Array[{ identifier: Integer, sample_offset: Integer, label: String? }] cue_points_a, Array[{ identifier: Integer, sample_offset: Integer, label: String? }] cue_points_b) -> bool

Expand Down
34 changes: 25 additions & 9 deletions sig/generated/wavesync/set_editor.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ module Wavesync
class SetEditor
KEY_MAP: untyped

attr_accessor player_state: Symbol

attr_reader selected: untyped

attr_reader set: untyped

attr_reader ui: untyped

attr_writer player_track: untyped

attr_writer player_index: untyped

attr_writer player_offset: untyped

attr_writer player_started_at: untyped

# : (Set set, String library_path) -> void
def initialize: (Set set, String library_path) -> void

Expand All @@ -13,15 +29,15 @@ module Wavesync
# : (String? path) -> (String | Integer)?
def track_bpm: (String? path) -> (String | Integer)?

# : ((String | Integer)? source_bpm, (String | Integer)? target_bpm) -> Float?
def pitch_shift_semitones: ((String | Integer)? source_bpm, (String | Integer)? target_bpm) -> Float?

# : (String? path) -> Float?
def track_duration: (String? path) -> Float?

# : (String? path) -> Array[Float]
def track_cue_fractions: (String? path) -> Array[Float]

# : ((String | Integer)? source_bpm, (String | Integer)? target_bpm) -> Float?
def pitch_shift_semitones: ((String | Integer)? source_bpm, (String | Integer)? target_bpm) -> Float?

# : (Float semitones) -> String
def format_pitch_shift: (Float semitones) -> String

Expand All @@ -42,12 +58,6 @@ module Wavesync
# : (String absolute) -> String
def relative_path: (String absolute) -> String

# : (String relative) -> String
def display_name: (String relative) -> String

# : (?String title) -> void
def render: (?String title) -> void

# : (Float? seconds) -> String?
def format_duration: (Float? seconds) -> String?

Expand All @@ -66,6 +76,12 @@ module Wavesync
# : (Float elapsed, Float total_duration) -> String
def remaining_display: (Float elapsed, Float total_duration) -> String

# : (String relative) -> String
def display_name: (String relative) -> String

# : (?String title) -> void
def render: (?String title) -> void

# : (Integer index, String relative, bool selected, bool playing, ?bpm: (String | Integer)?, ?pitch_shift: Float?, ?duration: Float?, ?duration_col_width: Integer, ?cue_fractions: Array[Float]) -> void
def render_track: (Integer index, String relative, bool selected, bool playing, ?bpm: (String | Integer)?, ?pitch_shift: Float?, ?duration: Float?, ?duration_col_width: Integer, ?cue_fractions: Array[Float]) -> void

Expand Down
Loading