diff --git a/src/main.py b/src/main.py index 6f622de..39e98dc 100644 --- a/src/main.py +++ b/src/main.py @@ -9,13 +9,13 @@ import mp3 if __name__ == "__main__": print("Loading project...") - test_project = Project(song_length=8) + """test_project = Project(song_length=64,bpm=120) drum_channel = ProjectChannel( test_project, name="Drums", - volume=5, - + volume=-5, + pan=-100 ) drum_channel.chunks.append(AudioChannelChunk( drum_channel, @@ -29,10 +29,42 @@ if __name__ == "__main__": *librosa.load("120 bpm amen break.mp3", mono=False, sr=test_project.sample_rate), name="120 bpm amen break.mp3" )) + drum_channel.chunks.append(AudioChannelChunk( + drum_channel, + position=2, + *librosa.load("120 bpm amen break.mp3", mono=False, sr=test_project.sample_rate), + name="120 bpm amen break.mp3" + )) + drum_channel.chunks.append(AudioChannelChunk( + drum_channel, + position=3, + *librosa.load("120 bpm amen break.mp3", mono=False, sr=test_project.sample_rate), + name="120 bpm amen break.mp3" + )) + drum_channel.chunks.append(AudioChannelChunk( + drum_channel, + position=4, + *librosa.load("120 bpm amen break.mp3", mono=False, sr=test_project.sample_rate), + name="120 bpm amen break.mp3" + )) + + piano_channel = ProjectChannel( + test_project, + name="Piano", + volume=-5, + pan=100 + ) + piano_channel.chunks.append(AudioChannelChunk( + piano_channel, + position=2, + *librosa.load("piano chords - Bmin 120BPM.wav", mono=False, sr=test_project.sample_rate), + name="piano chords - Bmin 120BPM.wav" + )) test_project.channels.append(drum_channel) + test_project.channels.append(piano_channel) - test_project.write_to_file("test_project.tdp") + test_project.write_to_file("test_project.tdp")""" test_project = Project.from_file("test_project.tdp") # start the ui diff --git a/src/project.py b/src/project.py index ec5b458..ca31aaa 100644 --- a/src/project.py +++ b/src/project.py @@ -86,18 +86,16 @@ chunk_type_associations = { } class ProjectChannel: - def __init__(self, project, name: str = "", volume: int = 0, pan: int = 0, mute: bool = False, solo: bool = False, chunks: list[ChannelChunk] = []): + def __init__(self, project, name: str = "", volume: int = 0, pan: int = 0, mute: bool = False, solo: bool = False, channel_chunks: list[ChannelChunk] = []): self.project = project self.name = name self.volume = volume self.pan = pan self.mute = mute self.solo = solo - self.chunks = chunks + self.chunks = [] - self.board = pedalboard.Pedalboard([ - pedalboard.Reverb() - ]) + self.board = pedalboard.Pedalboard() def pan_stereo(self, stereo, pan): pan = np.clip(pan, -1.0, 1.0) @@ -120,14 +118,14 @@ class ProjectChannel: buffer[start:end] += audio # apply effects - buffer = self.board(buffer, self.project.sample_rate) + #buffer = self.board(buffer, self.project.sample_rate) # apply volume gain = 10 ** (self.volume / 20) buffer *= gain # pan - self.pan_stereo(buffer, self.pan/100) + buffer = self.pan_stereo(buffer, self.pan/100) return buffer diff --git a/src/song_player.py b/src/song_player.py index 20499b1..59af3f5 100644 --- a/src/song_player.py +++ b/src/song_player.py @@ -35,7 +35,7 @@ class SongPlayer: out[:] = chunk self.playhead = end - self.timeline.run_worker(self.update_visual_playhead()) + async def update_visual_playhead(self): # get how many bars into the song we are @@ -56,6 +56,7 @@ class SongPlayer: def pause(self): self.paused = True + self.stream.close() play_btn = self.timeline.app.query_one("#play-button") play_btn.variant = "success" @@ -66,14 +67,20 @@ class SongPlayer: self.project = project self.audio = project.render() - try: - self.paused = False + + try: + if not self.stream.closed: + self.stream.close() + self.stream = sd.OutputStream( samplerate=project.sample_rate, channels=self.audio.shape[1] if self.audio.ndim > 1 else 1, - callback=self.play_callback + callback=self.play_callback, + blocksize=256 ) + self.paused = False + self.stream.start() diff --git a/src/test_project.tdp b/src/test_project.tdp index 591cb24..8a5b7a4 100644 Binary files a/src/test_project.tdp and b/src/test_project.tdp differ diff --git a/src/ui/widgets/timeline.py b/src/ui/widgets/timeline.py index f97ec13..6f9f2dc 100644 --- a/src/ui/widgets/timeline.py +++ b/src/ui/widgets/timeline.py @@ -127,9 +127,11 @@ class Timeline(Vertical): with VerticalScroll(id="rows"): for channel in self.app.project.channels: with TimelineRow() as row: - row.styles.width = self.bar_offset * self.app.project.song_length + row.styles.width = self.bar_offset * self.app.project.song_length + for chunk in channel.chunks: + if chunk.chunk_type == ChunkType.CHUNK: yield Chunk(chunk_name=chunk.name, bar_pos=chunk.position) elif chunk.chunk_type == ChunkType.AUDIO: