summaryrefslogtreecommitdiff
path: root/python/demos/demo_reading_speed.py
blob: 90739f3f3a57a75520823f1a09b8c9d295799a21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#! /usr/bin/env python
# -*- coding: utf-8 -*-

"""

Compare the speed of several methods for reading and loading a sound file.

Optionally, this file can make use of the following packages:

    - audioread     https://github.com/beetbox/audioread
    - scipy         https://scipy.org
    - librosa       https://github.com/bmcfee/librosa
    - pydub         https://github.com/jiaaro/pydub

Uncomment the function names below and send us your speed results!

"""


test_functions = [
            "read_file_aubio",
            "load_file_aubio",
            #"load_file_scipy",
            #"load_file_scipy_mmap",
            #"read_file_audioread",
            #"load_file_librosa",
            #"read_file_pydub",
            #"load_file_pydub",
            ]


import numpy as np

def read_file_audioread(filename):
    import audioread
    # taken from librosa.util.utils
    def convert_buffer_to_float(buf, n_bytes = 2, dtype = np.float32):
        # Invert the scale of the data
        scale = 1./float(1 << ((8 * n_bytes) - 1))
        # Construct the format string
        fmt = '<i{:d}'.format(n_bytes)
        # Rescale and format the data buffer
        out = scale * np.frombuffer(buf, fmt).astype(dtype)
        return out

    with audioread.audio_open(filename) as f:
        total_frames = 0
        for buf in f:
            samples = convert_buffer_to_float(buf)
            samples = samples.reshape(f.channels, -1)
            total_frames += samples.shape[1]
        return total_frames, f.samplerate

def load_file_librosa(filename):
    import librosa
    y, sr = librosa.load(filename, sr = None)
    #print y.mean(), y.shape
    return len(y), sr

def load_file_scipy(filename):
    import scipy.io.wavfile
    sr, y = scipy.io.wavfile.read(filename)
    y = y.astype('float32') / 32767
    #print y.mean(), y.shape
    return len(y), sr

def load_file_scipy_mmap(filename):
    import scipy.io.wavfile
    sr, y = scipy.io.wavfile.read(filename, mmap = True)
    #print y.mean(), y.shape
    return len(y), sr

def read_file_pydub(filename):
    from pydub import AudioSegment
    song = AudioSegment.from_file(filename)
    song.get_array_of_samples()
    return song.frame_count(), song.frame_rate

def load_file_pydub(filename):
    from pydub import AudioSegment
    song = AudioSegment.from_file(filename)
    y = np.asarray(song.get_array_of_samples(), dtype = 'float32')
    y = y.reshape(song.channels, -1) / 32767.
    return song.frame_count(), song.frame_rate

def read_file_aubio(filename):
    import aubio
    f = aubio.source(filename, hop_size = 1024)
    total_frames = 0
    while True:
        _, read = f()
        total_frames += read
        if read < f.hop_size: break
    return total_frames, f.samplerate

def load_file_aubio(filename):
    import aubio
    f = aubio.source(filename, hop_size = 1024)
    y = np.zeros(f.duration, dtype = aubio.float_type)
    total_frames = 0
    while True:
        samples, read = f()
        y[total_frames:total_frames + read] = samples[:read]
        total_frames += read
        if read < f.hop_size: break
    assert len(y) == total_frames
    #print y.mean(), y.shape
    return total_frames, f.samplerate

def test_speed(function, filename):
    times = []
    for _ in range(10):
        start = time.time()
        try:
            total_frames, samplerate = function(filename)
        except ImportError as e:
            print ("error: failed importing {:s}".format(e))
            return
        elapsed = time.time() - start
        #print ("{:5f} ".format(elapsed)),
        times.append(elapsed)

    #print
    times = np.array(times)
    duration_min = int(total_frames/float(samplerate) // 60)
    str_format = '{:25s} took {:5f} seconds avg (±{:5f}) to run on a ~ {:d} minutes long file'
    print (str_format.format(function.__name__, times.mean(), times.std(), duration_min ))

if __name__ == '__main__':
    import sys, time
    if len(sys.argv) < 2:
        print ("not enough arguments")
        sys.exit(1)
    filename = sys.argv[1]

    for f in test_functions:
        # get actual function from globals
        test_function = globals()[f]
        test_speed(test_function, filename)