def main(): nElectrodes = 21 #number of electrodes lowFreq = 200 #lower frequency boudary [Hz] highFreq = 5000 #higher frequency boudary [Hz] winSize = 6 #window size [ms] stepSize = .5 #step size [ms] inputMethod = None while inputMethod != 'fourier' and inputMethod != '1' and inputMethod != 'gamma' and inputMethod != '2': inputMethod = input( 'Please enter the method you want to use (fourier,1/gamma,2): ' ) #valid inputs: ('fourier','1'), ('gamma','2') if inputMethod == 'fourier' or inputMethod == '1': method = 'fourier' elif inputMethod == 'gamma' or inputMethod == '2': method = 'gamma' inFileName = './SoundData/tiger.wav' #inFileName = './SoundData/vowels.wav' #inFileName = './SoundData/Mond_short.wav' if (('inFileName' in locals()) or ('inFileName' in globals())) and inFileName != None: snd = thSound.Sound(inFileName) else: snd = thSound.Sound() inFileName = snd.source sampleRate = snd.rate outStem, outSuffix = inFileName.rsplit('.', 1) outFileName = outStem + '_out.wav' if snd.data.ndim < 2: snd.data = np.reshape(snd.data, (len(snd.data), 1)) soundData = np.zeros(snd.data.shape) for lrIdx in range(snd.data.shape[1]): stimuli, freq = calculateStimuliWindowed(snd.data[:, lrIdx], sampleRate, nElectrodes, lowFreq, highFreq, winSize, stepSize, method) ################################################################## ## At this point, stimuli contains the stimulation intensities, ## ## one row per electrode. Based on this, the sound a wearer of ## ## a CI might percieve is estimated. ## ################################################################## for lrIdx in range(snd.data.shape[1]): soundData[:, lrIdx] = simulateSound(stimuli, freq, sampleRate) writeSoundToFile(soundData, sampleRate, outFileName)
def writeSoundToFile(outData, sampleRate, outFileName=None): if not outData[0].dtype == np.dtype('int16'): defaultAmp = 2**13 outData *= defaultAmp / np.max(outData) outData = np.int16(outData) ### this section is a copy-paste from thLib's writeWav, as it can't handle stereo sound if outFileName is None: (outFile, outDir) = ui.savefile('Write sound to ...', '*.wav') if outFile == 0: print('Output discarded.') return 0 else: outFileName = os.path.join(outDir, outFile) else: outDir = os.path.abspath(os.path.dirname(outFileName)) outFile = os.path.basename(outFileName) # outFileName = tkFileDialog.asksaveasfilename() scipy.io.wavfile.write(str(outFileName), int(sampleRate), outData) print('Sounddata written to ' + outFile + ', with a sample rate of ' + str(sampleRate)) print('OutDir: ' + outDir) ### #ugly hack, s.t. playing stereo is possible #(thLib accepts stereo files and keeps them stereo, but it is not possible # to construct stereo Sound objects, except from files.) dummySnd = thSound.Sound(outFileName) dummySnd.play()
def main(): nElectrodes = 21 lowFreq = 400 #hz highFreq = 5000 #hz winSize = 6 #ms stepSize = .5 #ms method = 'gamma' #alt: 'fourier', 'gamma' tailFactor = 5 #only takes effect if method='gamma'. determines #how lon inFileName = './SoundData/tiger.wav' #inFileName = './SoundData/vowels.wav' #inFileName = './SoundData/Mond_short.wav' if (('inFileName' in locals()) or ('inFileName' in globals())) and inFileName != None: snd = thSound.Sound(inFileName) else: snd = thSound.Sound() inFileName = snd.source sampleRate = snd.rate outStem, outSuffix = inFileName.rsplit('.', 1) outFileName = outStem + '_' + method + '_out.wav' if method == 'gamma': winTailSize = 5 * winSize else: winTailSize = winSize if snd.data.ndim < 2: snd.data = np.reshape(snd.data, (len(snd.data), 1)) soundData = np.zeros(snd.data.shape) for lrIdx in range(snd.data.shape[1]): stimuli, freq = calculateStimuliWindowed(snd.data[:, lrIdx], sampleRate, nElectrodes, lowFreq, highFreq, winSize, stepSize, winTailSize, method) for lrIdx in range(snd.data.shape[1]): soundData[:, lrIdx] = simulateSound(stimuli, freq, sampleRate) writeSoundToFile(soundData, sampleRate, outFileName)
def writeSoundToFile(outData, sampleRate, outFileName=None): """ Generates a sound file from outData Args: otuData: array, output data representing the sound sampleRate: integer, sampling rate of the sound to be written outFileName: string, path and name of the output soundfile Returns: void """ ######################################################## ## this section is a slightly altered copy-paste from ## ## thLib's setData, as it couldn't originally deal ## ## with 2D arrays. ## ######################################################## if not outData[0].dtype == np.dtype('int16'): defaultAmp = 2**13 outData *= defaultAmp / np.max(outData) outData = np.int16(outData) ######################################################### ## this section is a copy-paste from thLib's writeWav, ## ## as setData wouldn't accept Stereo sound. ## ######################################################### if outFileName is None: (outFile, outDir) = ui.savefile('Write sound to ...', '*.wav') if outFile == 0: print('Output discarded.') return 0 else: outFileName = os.path.join(outDir, outFile) else: outDir = os.path.abspath(os.path.dirname(outFileName)) outFile = os.path.basename(outFileName) # outFileName = tkFileDialog.asksaveasfilename() scipy.io.wavfile.write(str(outFileName), int(sampleRate), outData) print('Sounddata written to ' + outFile + ', with a sample rate of ' + str(sampleRate)) print('OutDir: ' + outDir) ################################# ## End of copy-pasted sections ## ################################# #ugly hack, s.t. playing stereo is possible #(thLib accepts stereo files and keeps them stereo, but it is not possible # to construct stereo Sound objects, except from files.) dummySnd = thSound.Sound(outFileName) dummySnd.play()
def calcTransform(ci, inSound): ''' Step through the whole file to calculate i) the stimulation parameters, and ii) the reconstructed output ''' #Allocate the required memory StimStrength = np.zeros(ci.dataNum) ReAssembled = np.zeros(ci.dataNum) time = np.arange(ci.winStepSize_pts) / float(inSound.rate) for ii in progressbar( range(1, ci.dataNum - ci.winCalcSize_pts + 2, ci.winStepSize_pts), 'Computing ', 25): # Calculate PowerSpectrum Pxx, freq = pSpect(inSound.data[ii:(ii + ci.winCalcSize_pts - 1)], inSound.rate) # set averaging ranges, only on the first loop # I have to do this here, since I need "freq" if ii == 1: average_freqs = np.zeros([len(freq), ci.Electrodes_num]) stim_data = np.zeros([ci.Electrodes_num, len(time)]) for jj in range(ci.Electrodes_num): average_freqs[((freq > ci.sample_freqs[jj]) * (freq < ci.sample_freqs[jj + 1])), jj] = 1 stim_freq = np.mean(ci.sample_freqs[jj:(jj + 2)]) # "stim_data" are the sine-waves corresponding to each electrode stimulation stim_data[jj, :] = np.sin(2 * np.pi * stim_freq * time) # Average over the requested bins # The square root has to be taken, to get the amplitude StimStrength = np.sqrt(Pxx).dot(average_freqs) # Reassemble the output NewStim = StimStrength.dot(stim_data) ReAssembled[ii:(ii + ci.winStepSize_pts)] = NewStim # Return the output as normalized 32-bit integer outFloat = (ReAssembled - np.min(ReAssembled)) outSound = (outFloat / np.max(outFloat) * (2**31 - 1)).astype(np.int32) return Sound.Sound(inData=outSound.astype(np.float64), inRate=inSound.rate)
def main(inFile=None): ''' Main file. It * selects the sound source, and gets the data * defines the cochlear implant * calculates the simulated sound * writes the data to an out-file ''' inSound = Sound.Sound(inFile) # inSound.play() newCi = CochleaImplant(inSound) ciSound = calcTransform(newCi, inSound) # Determine the name of the out-file, write and play it inFile = os.path.basename(str(inSound.source)) inBase, inExt = inFile.split('.') fullOutFile = inBase + '_out.' + inExt ciSound.source = fullOutFile ciSound.writeWav(fullOutFile) ciSound.play()