Source code for brownify.actions

import librosa
import numpy as np

from brownify.models import Track


[docs]class Brownifier: @staticmethod def _is_stereo(track: Track) -> bool: return track.num_channels == 2 @staticmethod def _change_pitch_stereo( track: Track, n_steps: int, bins_per_octave: int ) -> Track: track.audio[:, 0] = librosa.effects.pitch_shift( track.audio[:, 0], track.sample_rate, n_steps=n_steps, bins_per_octave=bins_per_octave, ) track.audio[:, 1] = librosa.effects.pitch_shift( track.audio[:, 1], track.sample_rate, n_steps=n_steps, bins_per_octave=bins_per_octave, ) return track @staticmethod def _change_pitch_mono( track: Track, n_steps: int, bins_per_octave: int ) -> Track: track.audio = librosa.effects.pitch_shift( track.audio, track.sample_rate, n_steps=n_steps, bins_per_octave=bins_per_octave, ) return track
[docs] @staticmethod def change_pitch( track: Track, n_steps: int, bins_per_octave: int = 12 ) -> Track: """Change the pitch of the track without changing the track speed Args: track: The track to modify n_steps: Number of steps to modify by (positive or negative) bins_per_octave: Number of steps in an octave. Defaults to 12. Returns: The track with the pitch changed """ if Brownifier._is_stereo(track): return Brownifier._change_pitch_stereo( track, n_steps, bins_per_octave ) else: return Brownifier._change_pitch_mono( track, n_steps, bins_per_octave )
[docs] @staticmethod def flat(track: Track) -> Track: """Make the track flat by one semitone Args: track: The track to modify Returns: The track which is now flat """ return Brownifier.change_pitch(track, n_steps=-1)
[docs] @staticmethod def sharp(track: Track) -> Track: """Make the track sharp by one semitone Args: track: The track to modify Returns: The track which is now sharp """ return Brownifier.change_pitch(track, n_steps=1)
[docs] @staticmethod def half_flat(track: Track) -> Track: """Make the track flat by one quarter tone Args: track: The track to modify Returns: The track which is now half-flat """ return Brownifier.change_pitch(track, n_steps=-1, bins_per_octave=24)
[docs] @staticmethod def half_sharp(track: Track) -> Track: """Make the track sharp by one quarter tone Args: track: The track to modify Returns: The track which is now half-sharp """ return Brownifier.change_pitch(track, n_steps=1, bins_per_octave=24)
[docs] @staticmethod def octave_up(track: Track) -> Track: """Move the track up by a full octave Args: track: The track to modify Returns: The track which is now an octave higher """ return Brownifier.change_pitch(track, n_steps=12)
[docs] @staticmethod def octave_down(track: Track) -> Track: """Move the track down by a full octave Args: track: The track to modify Returns: The track which is now an octave lower """ return Brownifier.change_pitch(track, n_steps=-12)
[docs] @staticmethod def time_shift(track: Track, seconds_shift: float) -> Track: """Shift the track forward or backward in time The track is shifted forward or backward in time by rolling the values and wrapping where the track ends back to the beginning or vice-versa Args: track: The track to modify seconds_shift: The number of seconds to shift by Returns: The track which has been shifted in time """ seconds_per_sample = 1 / track.sample_rate samples_shift = round(seconds_shift / seconds_per_sample) track.audio = np.roll(track.audio, samples_shift) return track
[docs] @staticmethod def early(track: Track) -> Track: """Shift the track forward in time by about a 35 milliseconds Args: track: The track to modify Returns: The track which is now early """ return Brownifier.time_shift(track, -0.035)
[docs] @staticmethod def late(track: Track) -> Track: """Shift a track backward in time by about a 35 milliseconds Args: track: The track to modify Returns: The track which is now late """ return Brownifier.time_shift(track, 0.035)