#!/usr/bin/env python2 # -*- coding: utf-8 -*- """ USAGE: morphagene_directory.py -d -o ' Script will go through and splice all wave-files together in alphabetic order and place a marker in between. Requires all wave-files in directory to have the same number of channels and bitrate! Does not require input file to be 48000Hz, but .WAV-files must be stereo. See the Morphagene manual for naming conventions of output files: http://www.makenoisemusic.com/content/manuals/morphagene-manual.pdf # see http://stackoverflow.com/questions/15576798/create-32bit-float-wav-file-in-python # see... http://blog.theroyweb.com/extracting-wav-file-header-information-using-a-python-script # marker code from Joseph Basquin [https://gist.github.com/josephernest/3f22c5ed5dabf1815f16efa8fa53d476] """ import sys, getopt import struct import numpy as np from scipy import interpolate import gzip import os def float32_wav_file(file_name, sample_array, sample_rate, markers=None, verbose=False): (M,N)=sample_array.shape #print "len sample_array=(%d,%d)" % (M,N) byte_count = M * N * 4 # (len(sample_array)) * 4 # 32-bit floats wav_file = "" # write the header wav_file += struct.pack(' new_rate, there may be aliasing / data loss. Input should be in column format, as the interpolation will be completed on each channel this way. Modified from: https://stackoverflow.com/questions/33682490/how-to-read-a-wav-file-using-scipy-at-a-different-sampling-rate ''' if old_rate != new_rate: # duration of audio duration = old_audio.shape[0] / old_rate # length of old and new audio time_old = np.linspace(0, duration, old_audio.shape[0]) time_new = np.linspace(0, duration, int(old_audio.shape[0] * new_rate / old_rate)) # fit old_audio into new_audio length by interpolation interpolator = interpolate.interp1d(time_old, old_audio.T) new_audio = interpolator(time_new).T return new_audio else: print('Conversion not needed, old and new rates match') return old_audio # conversion not needed def main(argv): inputdirectory = '' outputfile = '' try: opts, args = getopt.getopt(argv,"hd:o:",["inputdirectory=","outputfile="]) except getopt.GetoptError: print('Error in usage, correct format:\n'+\ 'morphagene_directory.py -d -o ') sys.exit(2) for opt, arg in opts: if opt == '-h': print('morphagene_directory.py -d -o ') sys.exit() elif opt in ("-d", "--inputdirectory"): inputdirectory = arg elif opt in ("-o", "--outputfile"): outputfile = arg print('Input directory: %s'%inputdirectory) print('Output Morphagene reel: %s'%outputfile) ########################################################################### ''' Write single file, to Morphagene 32bit WAV file at 48000hz sample rate. ''' ########################################################################### morph_srate = 48000 # required samplerate for Morphagene # find .wav-files in inputdirectory wavfiles = [] entries = sorted(os.listdir(inputdirectory)) for entry in entries: if entry.endswith('.wav'): wavfiles.append("{0}/{1}".format(inputdirectory,entry)) first_num_channels = None first_bits_per_sample = None allwaves = None markers = [] for wavfile in wavfiles: # read pertinent info from audio file, exit if input wave file is broken try: (array,sample_rate,num_channels,bits_per_sample)=wav_file_read(wavfile, verbose=False) if first_num_channels == None: first_num_channels = num_channels first_bits_per_sample = bits_per_sample else: if num_channels != first_num_channels or bits_per_sample != first_bits_per_sample: print('All wave files must have the same number of channels and bitrate') sys.exit() except: print('Input .wav file %s is poorly formatted, exiting'%wavfile) sys.exit() # check if input wav has a different rate than desired Morphagene rate, # and correct by interpolation if sample_rate != morph_srate: print("Correcting input sample rate %iHz to Morphagene rate %iHz"%(sample_rate,morph_srate)) # perform interpolation on each channel, then transpose back array = change_samplerate_interp(array.T,float(sample_rate),float(morph_srate)).T if allwaves == None: allwaves = np.array(array) markers.append(len(array[0])) else: #for a in array: allwaves = np.concatenate((allwaves,array), axis=1) markers.append(len(array[0]) + markers[-1]) markers.pop() # remove last marker # write wav file with additional cue markers from labels float32_wav_file(outputfile,allwaves,morph_srate,markers=markers) print('Saved Morphagene reel with %i splices: %s'%(len(markers)+1,outputfile)) if __name__ == "__main__": main(sys.argv[1:])