peterf@2
|
1 #!/usr/bin/env python
|
peterf@2
|
2 '''CREATED:2014-05-22 16:43:44 by Brian McFee <brm2132@columbia.edu>
|
peterf@2
|
3
|
peterf@2
|
4 Pitch-shift a recording to be in A440 tuning.
|
peterf@2
|
5
|
peterf@2
|
6 Usage: ./adjust_tuning.py [-h] input_file output_file
|
peterf@2
|
7 '''
|
peterf@2
|
8 from __future__ import print_function
|
peterf@2
|
9
|
peterf@2
|
10 import argparse
|
peterf@2
|
11 import sys
|
peterf@2
|
12 import librosa
|
peterf@2
|
13
|
peterf@2
|
14
|
peterf@2
|
15 def adjust_tuning(input_file, output_file):
|
peterf@2
|
16 '''Load audio, estimate tuning, apply pitch correction, and save.'''
|
peterf@2
|
17 print('Loading ', input_file)
|
peterf@2
|
18 y, sr = librosa.load(input_file)
|
peterf@2
|
19
|
peterf@2
|
20 print('Separating harmonic component ... ')
|
peterf@2
|
21 y_harm = librosa.effects.harmonic(y)
|
peterf@2
|
22
|
peterf@2
|
23 print('Estimating tuning ... ')
|
peterf@2
|
24 # Just track the pitches associated with high magnitude
|
peterf@2
|
25 tuning = librosa.feature.estimate_tuning(y=y_harm, sr=sr)
|
peterf@2
|
26
|
peterf@2
|
27 print('{:+0.2f} cents'.format(100 * tuning))
|
peterf@2
|
28 print('Applying pitch-correction of {:+0.2f} cents'.format(-100 * tuning))
|
peterf@2
|
29 y_tuned = librosa.effects.pitch_shift(y, sr, -tuning)
|
peterf@2
|
30
|
peterf@2
|
31 print('Saving tuned audio to: ', output_file)
|
peterf@2
|
32 librosa.output.write_wav(output_file, y_tuned, sr)
|
peterf@2
|
33
|
peterf@2
|
34
|
peterf@2
|
35 def process_arguments(args):
|
peterf@2
|
36 '''Argparse function to get the program parameters'''
|
peterf@2
|
37
|
peterf@2
|
38 parser = argparse.ArgumentParser(description='Tuning adjustment example')
|
peterf@2
|
39
|
peterf@2
|
40 parser.add_argument('input_file',
|
peterf@2
|
41 action='store',
|
peterf@2
|
42 help='path to the input file (wav, mp3, etc)')
|
peterf@2
|
43
|
peterf@2
|
44 parser.add_argument('output_file',
|
peterf@2
|
45 action='store',
|
peterf@2
|
46 help='path to store the output wav')
|
peterf@2
|
47
|
peterf@2
|
48 return vars(parser.parse_args(args))
|
peterf@2
|
49
|
peterf@2
|
50
|
peterf@2
|
51 if __name__ == '__main__':
|
peterf@2
|
52 # Get the parameters
|
peterf@2
|
53 params = process_arguments(sys.argv[1:])
|
peterf@2
|
54
|
peterf@2
|
55 # Run the beat tracker
|
peterf@2
|
56 adjust_tuning(params['input_file'], params['output_file'])
|