Skip to content

Commit

Permalink
Add scipy-powered filters and bump version
Browse files Browse the repository at this point in the history
  • Loading branch information
jiaaro committed Oct 12, 2016
1 parent 66ff686 commit be1581b
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 2 deletions.
17 changes: 16 additions & 1 deletion pydub/effects.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@
xrange = range


@register_pydub_effect
def apply_mono_filter_to_each_channel(seg, filter_fn):
n_channels = seg.channels

channel_segs = seg.split_to_mono()
channel_segs = [filter_fn(channel_seg) for channel_seg in channel_segs]

out_data = seg.get_array_of_samples()
for channel_i, channel_seg in enumerate(channel_segs):
for sample_i, sample in enumerate(channel_seg.get_array_of_samples()):
index = (sample_i * n_channels) + channel_i
out_data[index] = sample

return seg._spawn(out_data.tostring())


@register_pydub_effect
def normalize(seg, headroom=0.1):
Expand Down Expand Up @@ -303,4 +318,4 @@ def apply_gain_stereo(seg, left_gain=0.0, right_gain=0.0):

return seg._spawn(data=output,
overrides={'channels': 2,
'frame_width': 2 * seg.sample_width})
'frame_width': 2 * seg.sample_width})
60 changes: 60 additions & 0 deletions pydub/scipy_effects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""
This module provides scipy versions of high_pass_filter, and low_pass_filter
as well as an additional band_pass_filter.
Of course, you will need to install scipy for these to work.
When this module is imported the high and low pass filters are used when calling
audio_segment.high_pass_filter() and audio_segment.high_pass_filter() instead
of the slower, less powerful versions provided by pydub.effects.
"""
from scipy.signal import butter, sosfilt
from .utils import register_pydub_effect


def _mk_butter_filter(freq, type, order):
"""
Args:
freq: The cutoff frequency for highpass and lowpass filters. For
band filters, a list of [low_cutoff, high_cutoff]
type: "lowpass", "highpass", or "band"
order: nth order butterworth filter (default: 5th order)
Returns:
function which can filter a mono audio segment
"""
def filter_fn(seg):
assert seg.channels == 1

nyq = 0.5 * seg.frame_rate
try:
freqs = [f / nyq for f in freq]
except TypeError:
freqs = freq / nyq

sos = butter(order, freqs, btype=type, output='sos')
y = sosfilt(sos, seg.get_array_of_samples())

return seg._spawn(y.astype(seg.array_type).tostring())

return filter_fn


@register_pydub_effect
def band_pass_filter(seg, low_cutoff_freq, high_cutoff_freq, order=5):
filter_fn = _mk_butter_filter([low_cutoff_freq, high_cutoff_freq], 'band', order=order)
return seg.apply_mono_filter_to_each_channel(filter_fn)


@register_pydub_effect
def high_pass_filter(seg, cutoff_freq, order=5):
filter_fn = _mk_butter_filter(cutoff_freq, 'highpass', order=order)
return seg.apply_mono_filter_to_each_channel(filter_fn)


@register_pydub_effect
def low_pass_filter(seg, cutoff_freq, order=5):
filter_fn = _mk_butter_filter(cutoff_freq, 'lowpass', order=order)
return seg.apply_mono_filter_to_each_channel(filter_fn)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setup(
name='pydub',
version='0.16.5',
version='0.16.6',
author='James Robert',
author_email='jiaaro@gmail.com',
description='Manipulate audio with an simple and easy high level interface',
Expand Down

0 comments on commit be1581b

Please sign in to comment.