def smallSampleSize(): try: filePath = sys.argv[1] if os.path.exists(filePath): wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: print "File is not a wave file" return dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() timeCodeSampleRate = int(sampleRate * 1.001) byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() frameNumber = 0 print datetime.datetime.now() with open(filePath, 'rb') as f: startTime = datetime.datetime.now() f.seek(dataStartPos) data_size = int( (sampleRate * 1.001) / 24) #1 frame of audio at 23.98 or 48048 sample rate dataToReadChunkSize = data_size * byteWidth #examine 160 seconds of data dataRemaining = (160 * timeCodeSampleRate ) * byteWidth * numberOfChannels #dataLength while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) dataRemaining -= len(data) print pctimecode.convertUnsignedLongLongToTimeCode( wavefile.timestamp + (frameNumber * data_size), timeCodeSampleRate, 24) frameNumber += 1 for channel in range(0, numberOfChannels): subdata = "" for x in range(channel * byteWidth, len(data), byteWidth * numberOfChannels): # subdata.extend(data[x:x+3]) subdata += (data[x] + data[x + 1] + data[x + 2]) print ultimateFreqAndPowerForData( subdata, byteWidth, sampleRate) print datetime.datetime.now() else: print "The file", filename, "doesn't exist" except IndexError as e: print "No file was passed in as a variable"
def findTwoPop(): try: filePath = sys.argv[1] if os.path.exists(filePath): wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: print "File is not a wave file" return dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() with open(filePath, 'rb') as f: startTime = datetime.datetime.now() #1 frame of audio at 23.98 or 48048 sample rate data_size = 2002 #position at which to examine startOffset = int(round( sampleRate * 1.001)) * 148 * byteWidth * numberOfChannels startOffset -= (data_size * byteWidth * numberOfChannels * 2) dataStartPos = dataStartPos + startOffset f.seek(dataStartPos) if dataStartPos > dataLength: print "file is too short to analyze" return dataToReadChunkSize = data_size * byteWidth * numberOfChannels dataRemaining = data_size * byteWidth * numberOfChannels * 6 while dataRemaining > 0: data = f.read(dataToReadChunkSize) print pcwave dataRemaining -= dataToReadChunkSize print "Next Sample" for channel in range(0, numberOfChannels): subdata = "" for x in range(channel * byteWidth, len(data), byteWidth * numberOfChannels): # subdata.extend(data[x:x+3]) subdata += (data[x] + data[x + 1] + data[x + 2]) # print anaylyzeDataWithZeroCrossing(subdata, byteWidth, sampleRate) result = ultimateFreqAndPowerForData( subdata, byteWidth, sampleRate) if math.isnan(result[0]) or result[1] < -65.0: print '\tDisregard', round(result[0]), result[1] elif result[0] < 1005 and result[0] > 995: print '\tMatch', round(result[0]), result[1] else: print '\tOops', round(result[0]), result[1] else: print "The file", filename, "doesn't exist" except IndexError as e: print "No file was passed in as a variable"
def multichannel(): try: filePath = sys.argv[1] if os.path.exists(filePath): wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: print "File is not a wave file" return dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() timeCodeSampleRate = int(math.ceil(48000 * 1.001)) byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() data_size = 48048 #1 second of audio print timeCodeSampleRate print pctimecode.convertUnsignedLongLongToTimeCode( wavefile.timestamp, timeCodeSampleRate, 24) second = 0 with open(filePath, 'rb') as f: startTime = datetime.datetime.now() f.seek(dataStartPos) dataToReadChunkSize = sampleRate * byteWidth * numberOfChannels dataRemaining = dataLength while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) dataRemaining -= len(data) print wavefile.timestamp print pctimecode.convertUnsignedLongLongToTimeCode( wavefile.timestamp + (second * data_size), timeCodeSampleRate, 24) for channel in range(0, numberOfChannels): subdata = "" for x in range(channel * byteWidth, len(data), byteWidth * numberOfChannels): subdata += (data[x] + data[x + 1] + data[x + 2]) print highestAndNextHighestFreqAndPowerForData( subdata, byteWidth, sampleRate) second += 1 else: print "The file", filename, "doesn't exist" except IndexError as e: print "No file was passed in as a variable"
def findTwoPop(): try: filePath = sys.argv[1] if os.path.exists(filePath): wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: print "File is not a wave file" return dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() with open(filePath, 'rb') as f: startTime = datetime.datetime.now() #1 frame of audio at 23.98 or 48048 sample rate data_size = 2002 #position at which to examine startOffset = int(round(sampleRate * 1.001)) * 148 * byteWidth * numberOfChannels startOffset -= (data_size * byteWidth * numberOfChannels * 2) dataStartPos = dataStartPos + startOffset f.seek(dataStartPos) if dataStartPos > dataLength: print "file is too short to analyze" return dataToReadChunkSize = data_size*byteWidth*numberOfChannels dataRemaining = data_size*byteWidth*numberOfChannels*6 while dataRemaining > 0: data = f.read(dataToReadChunkSize) print pcwave dataRemaining -= dataToReadChunkSize print "Next Sample" for channel in range(0, numberOfChannels): subdata = "" for x in range(channel*byteWidth,len(data),byteWidth*numberOfChannels): # subdata.extend(data[x:x+3]) subdata += (data[x] + data[x+1] + data[x+2]) # print anaylyzeDataWithZeroCrossing(subdata, byteWidth, sampleRate) result = ultimateFreqAndPowerForData(subdata, byteWidth, sampleRate) if math.isnan(result[0]) or result[1] < -65.0: print '\tDisregard', round(result[0]), result[1] elif result[0] < 1005 and result[0] > 995: print '\tMatch', round(result[0]), result[1] else: print '\tOops', round(result[0]), result[1] else: print "The file",filename,"doesn't exist" except IndexError as e: print "No file was passed in as a variable"
def smallSampleSize(): try: filePath = sys.argv[1] if os.path.exists(filePath): wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: print "File is not a wave file" return dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() timeCodeSampleRate = int(sampleRate * 1.001) byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() frameNumber = 0 print datetime.datetime.now() with open(filePath, 'rb') as f: startTime = datetime.datetime.now() f.seek(dataStartPos) data_size = int((sampleRate * 1.001) / 24) #1 frame of audio at 23.98 or 48048 sample rate dataToReadChunkSize = data_size*byteWidth #examine 160 seconds of data dataRemaining = (160*timeCodeSampleRate)*byteWidth*numberOfChannels #dataLength while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) dataRemaining -= len(data) print pctimecode.convertUnsignedLongLongToTimeCode(wavefile.timestamp + (frameNumber * data_size), timeCodeSampleRate, 24) frameNumber += 1 for channel in range(0, numberOfChannels): subdata = "" for x in range(channel*byteWidth,len(data),byteWidth*numberOfChannels): # subdata.extend(data[x:x+3]) subdata += (data[x] + data[x+1] + data[x+2]) print ultimateFreqAndPowerForData(subdata, byteWidth, sampleRate) print datetime.datetime.now() else: print "The file",filename,"doesn't exist" except IndexError as e: print "No file was passed in as a variable"
def multichannel(): try: filePath = sys.argv[1] if os.path.exists(filePath): wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: print "File is not a wave file" return dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() timeCodeSampleRate = int(math.ceil(48000 * 1.001)) byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() data_size = 48048 #1 second of audio print timeCodeSampleRate print pctimecode.convertUnsignedLongLongToTimeCode(wavefile.timestamp, timeCodeSampleRate, 24) second = 0 with open(filePath, 'rb') as f: startTime = datetime.datetime.now() f.seek(dataStartPos) dataToReadChunkSize = sampleRate*byteWidth*numberOfChannels dataRemaining = dataLength while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) dataRemaining -= len(data) print wavefile.timestamp print pctimecode.convertUnsignedLongLongToTimeCode(wavefile.timestamp + (second * data_size), timeCodeSampleRate, 24) for channel in range(0, numberOfChannels): subdata = "" for x in range(channel*byteWidth,len(data),byteWidth*numberOfChannels): subdata += (data[x] + data[x+1] + data[x+2]) print highestAndNextHighestFreqAndPowerForData(subdata, byteWidth, sampleRate) second += 1 else: print "The file",filename,"doesn't exist" except IndexError as e: print "No file was passed in as a variable"
def multichannel(): data_size = 48000 #1 second of audio frate = 48000.0 try: filePath = sys.argv[1] if os.path.exists(filePath): wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: print "File is not a wave file" return dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() print byteWidth, numberOfChannels second = 0 with open(filePath, 'rb') as f: startTime = datetime.datetime.now() f.seek(dataStartPos) dataToReadChunkSize = sampleRate*byteWidth*numberOfChannels dataRemaining = dataLength while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) dataRemaining -= len(data) print "Next second", second for channel in range(0, numberOfChannels): subdata = "" for x in range(channel*byteWidth,len(data),byteWidth*numberOfChannels): # subdata.extend(data[x:x+3]) subdata += (data[x] + data[x+1] + data[x+2]) print anaylyzeData(subdata, byteWidth, sampleRate) second += 1 else: print "The file",filename,"doesn't exist" except IndexError as e: print "No file was passed in as a variable"
def listOfTimeCodeValuesForFile(fullpath): wavefile = PCWaveFile(fullpath) if wavefile.isValidWaveFile() == False: print 'File is not valid' return tcList = [] sampleRate = wavefile.fmtChunkInfoDict['nSamplesPerSec'] tcList.append(wavefile.timestamp) tcList.append(pctimecode.convertUnsignedLongLongToTimeCode(wavefile.timestamp, sampleRate*1.001, 24)) #23976 tcList.append(pctimecode.convertUnsignedLongLongToTimeCode(wavefile.timestamp, sampleRate, 24)) #24 tcList.append(pctimecode.convertUnsignedLongLongToTimeCode(wavefile.timestamp, sampleRate, 25)) #25 tcList.append(pctimecode.convertUnsignedLongLongToTimeCode(wavefile.timestamp, sampleRate*1.001, 30)) #2997 tcList.append(pctimecode.convertUnsignedLongLongToTimeCode(wavefile.timestamp, sampleRate, 30)) #30 return tcList
def formatInformationForFile(filePath): wavefile = PCWaveFile(filePath) if wavefile == None or wavefile.isValidWaveFile() == False: badInfo = {} badInfo["fileName"] = os.path.basename(filePath) badInfo["fullPath"] = filePath badInfo["bitDepth"] = 0 badInfo["sampleRate"] = 0 badInfo["bextChunk"] = False badInfo["timeStamp"] = 0 badInfo["timeStampTC"] = "00:00:00:00" badInfo["regnChunk"] = False badInfo["channelCount"] = 0 badInfo["status"] = 'fail' badInfo["errors"] = ["{} is not a wave file.".format(os.path.basename(filePath)),] badInfo['fileLevels'] = {'status':'fail','layout':'unknown', "warningString":""} badInfo['headTones'] = {'status':'fail', 'resultString':'Unable to analyze head tones on account of invalid format.', "warningString":""} badInfo['pops'] = {'status':'fail', 'resultString':'Unable to analyze pops on account of invalid format.', "warningString":""} return badInfo info = {} info['fileName'] = os.path.basename(filePath) info['fullPath'] = filePath info['bitDepth'] = wavefile.numberOfBitsPerSample() info['sampleRate'] = wavefile.numberOfSamplesPerSecond() info['bextChunk'] = True if wavefile.hasBextChunk() else False info['timeStamp'] = wavefile.timestamp info['timeStampTC'] = prettyTimeCode2398(wavefile.timestamp, info['sampleRate']) info['regnChunk'] = True if wavefile.hasBextChunk() else False if wavefile.hasRegnChunk() == True: info['regnChunkUserTimeStamp'] = wavefile.regnChunkInfoDict['userTimeStamp'] info['regnChunkOriginalTimeStamp'] = wavefile.regnChunkInfoDict['originalTimeStamp'] info['channelCount'] = wavefile.numberOfChannels() if info['bitDepth'] != 24 or info['sampleRate'] != 48000: info['fileLevels'] = {'status':'fail','layout':'unknown', "warningString":""} info['headTones'] = {'status':'fail', 'resultString':'Unable to analyze head tones on account of invalid format.', "warningString":""} info['pops'] = {'status':'fail', 'resultString':'Unable to analyze pops on account of invalid format.', "warningString":""} else: info['fileLevels'] = analyzeLevels(filePath) info['headTones'] = analyzeHeadAlt(filePath) info['pops'] = analyzeTwoPopInEighths(filePath) return addStatusToInformation(info)
def examine2pop(): data_size = 48000/24 #1 second of audio frate = 48000.0 try: filePath = sys.argv[1] if os.path.exists(filePath): wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: print "File is not a wave file" return print wavefile.getFmtChunkDict() dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() byteWidth = wavefile.numberOfBytesPerSample() with open(filePath, 'rb') as f: startTime = datetime.datetime.now() f.seek(dataStartPos) dataToReadChunkSize = data_size*byteWidth dataRemaining = dataLength while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) print anaylyzeData(data, byteWidth, sampleRate) dataRemaining -= len(data) else: print "The file",filename,"doesn't exist" except: print "No file was passed in as a variable"
def analyzeTrackCorrelations(filePath): wavefile = None if os.path.exists(filePath): wavefile = PCWaveFile(filePath) else: return if wavefile == None or wavefile.isValidWaveFile() == False: return {"status":"fail", "resultString":"file is not a wavefile", "layout":"Unknown"} sampleRate = wavefile.fmtChunkInfoDict['nSamplesPerSec'] channelByteWidth = wavefile.fmtChunkInfoDict['wBitsPerSample'] / 8 bitsPerSample = wavefile.fmtChunkInfoDict['wBitsPerSample'] numberOfChannels = wavefile.fmtChunkInfoDict['nChannels'] packetByteWidth = channelByteWidth * numberOfChannels if numberOfChannels != 6: if numberOfChannels == 2: return {"status":"pass", "resultString":"File contains {} audio channels".format(numberOfChannels), "layout":"STEREO"} else: return {"status":"pass", "resultString":"File contains {} audio channels".format(numberOfChannels), "layout":"Unknown"} isSigned = True if channelByteWidth == 1: isSigned = False chunkPosition = wavefile.getDataChunk()['chunkPosition'] numberOfSamples = wavefile.getDataChunk()['chunkSize'] / packetByteWidth #open the file, read through the packets and do a running mean of each track in the file #what this does do is ASSUME that the input file is 24 bit signed data, otherwise 16 bit would be signed, but 8 bit wouldn't #not that 8 bit is an issue with open(filePath, 'rb') as f: f.seek(chunkPosition) blockWidthInSeconds = 1 samplesToReadBlockSize = (sampleRate * blockWidthInSeconds)/2 numberOfSamplesRemaining = numberOfSamples bufferAmount = samplesToReadBlockSize if numberOfSamples > samplesToReadBlockSize else numberOfSamples totalBlocksInFile = numberOfSamplesRemaining // samplesToReadBlockSize shouldReadEntireFile = False analysisSpacing = 0 numberOfAnalyses = 34 initialAnalyses = 0 if totalBlocksInFile < (2 * numberOfAnalyses): shouldReadEntireFile = True else: analysisSpacing = totalBlocksInFile / numberOfAnalyses startTime = datetime.datetime.now() constantBitDepth16 = pow(2,15) constantBitDepth24 = pow(2,23) #totalsCounter = RunningTotalCounter(pow(2,(bitsPerSample-1)), samplesToReadBlockSize, numberOfChannels) totalsCounter = RunningTotalCounter(constantBitDepth16, samplesToReadBlockSize, numberOfChannels) # you need to constrain the size of the input as we will be calculating RMS values which require exponential math while numberOfSamplesRemaining > 0: #read a buffer's amount of samples if numberOfSamplesRemaining > bufferAmount: bytesToRead = packetByteWidth * bufferAmount data = f.read(bytesToRead) numberOfSamplesRemaining -= (len(data)/packetByteWidth) if len(data) != bytesToRead: logging.error("IO Error: bytes returned do not match bytes asked for") #read a buffer's amount of samples analysis = {} for i in range(0,numberOfChannels): analysis[str(i)] = [] # read the file or current analysis into memory and sum all of the samples and raise to the 2nd pow if shouldReadEntireFile == True or (initialAnalyses % analysisSpacing == 0): for i in range(0, bytesToRead, packetByteWidth): subdata = data[i:(i+packetByteWidth)] for chPos in range(0, numberOfChannels): trackoffset = chPos * channelByteWidth extendedValue = les24toles32Value(''.join(subdata[trackoffset:trackoffset+channelByteWidth])) extendedValue = int(((1.0 * extendedValue) / constantBitDepth24) * constantBitDepth16) analysis[str(chPos)].append(extendedValue) maxValue = 0 track = 0 srcTrack = '0' for i in [0,1,2,3,4,5]: if int(srcTrack) == i: continue result = np.cov(analysis[srcTrack], analysis[str(i)])[0,1] if result > maxValue: maxValue = result track = i print srcTrack, "matches", track, "with", maxValue initialAnalyses += 1 else: data = f.read(packetByteWidth * numberOfSamplesRemaining) numberOfSamplesRemaining = 0 return {"OK":"OK"}
def formatInformationForFile(filePath): wavefile = PCWaveFile(filePath) if wavefile == None or wavefile.isValidWaveFile() == False: badInfo = {} badInfo["fileName"] = os.path.basename(filePath) badInfo["fullPath"] = filePath badInfo["bitDepth"] = 0 badInfo["sampleRate"] = 0 badInfo["bextChunk"] = False badInfo["timeStamp"] = 0 badInfo["timeStampTC"] = "00:00:00:00" badInfo["regnChunk"] = False badInfo["channelCount"] = 0 badInfo["status"] = 'fail' badInfo["errors"] = [ "{} is not a wave file.".format(os.path.basename(filePath)), ] badInfo['fileLevels'] = { 'status': 'fail', 'layout': 'unknown', "warningString": "" } badInfo['headTones'] = { 'status': 'fail', 'resultString': 'Unable to analyze head tones on account of invalid format.', "warningString": "" } badInfo['pops'] = { 'status': 'fail', 'resultString': 'Unable to analyze pops on account of invalid format.', "warningString": "" } return badInfo info = {} info['fileName'] = os.path.basename(filePath) info['fullPath'] = filePath info['bitDepth'] = wavefile.numberOfBitsPerSample() info['sampleRate'] = wavefile.numberOfSamplesPerSecond() info['bextChunk'] = True if wavefile.hasBextChunk() else False info['timeStamp'] = wavefile.timestamp info['timeStampTC'] = prettyTimeCode2398(wavefile.timestamp, info['sampleRate']) info['regnChunk'] = True if wavefile.hasBextChunk() else False if wavefile.hasRegnChunk() == True: info['regnChunkUserTimeStamp'] = wavefile.regnChunkInfoDict[ 'userTimeStamp'] info['regnChunkOriginalTimeStamp'] = wavefile.regnChunkInfoDict[ 'originalTimeStamp'] info['channelCount'] = wavefile.numberOfChannels() if info['bitDepth'] != 24 or info['sampleRate'] != 48000: info['fileLevels'] = { 'status': 'fail', 'layout': 'unknown', "warningString": "" } info['headTones'] = { 'status': 'fail', 'resultString': 'Unable to analyze head tones on account of invalid format.', "warningString": "" } info['pops'] = { 'status': 'fail', 'resultString': 'Unable to analyze pops on account of invalid format.', "warningString": "" } else: info['fileLevels'] = analyzeLevels(filePath) info['headTones'] = analyzeHeadAlt(filePath) info['pops'] = analyzeTwoPopInEighths(filePath) return addStatusToInformation(info)
def analyzeLevels(filePath): wavefile = None if os.path.exists(filePath): wavefile = PCWaveFile(filePath) else: return if wavefile == None or wavefile.isValidWaveFile() == False: return {"status":"fail", "resultString":"file is not a wavefile", "layout":"Unknown", "warningString":""} sampleRate = wavefile.fmtChunkInfoDict['nSamplesPerSec'] channelByteWidth = wavefile.fmtChunkInfoDict['wBitsPerSample'] / 8 bitsPerSample = wavefile.fmtChunkInfoDict['wBitsPerSample'] numberOfChannels = wavefile.fmtChunkInfoDict['nChannels'] packetByteWidth = channelByteWidth * numberOfChannels for title in ['MEHELP']: if title.lower() in filePath.lower(): layout = 'MONO' if numberOfChannels == 1 else 'MULTI-MONO' return {"status":"pass", "resultString":"The file contains {} in its file name and will not be analyzed.".format(title), "layout":layout, "warningString":""} if numberOfChannels != 6: if numberOfChannels == 2: return {"status":"pass", "resultString":"File contains {} audio channels".format(numberOfChannels), "layout":"STEREO", "warningString":""} else: return {"status":"pass", "resultString":"File contains {} audio channels".format(numberOfChannels), "layout":"Unknown", "warningString":""} isSigned = True if channelByteWidth == 1: isSigned = False chunkPosition = wavefile.getDataChunk()['chunkPosition'] numberOfSamples = wavefile.getDataChunk()['chunkSize'] / packetByteWidth #open the file, read through the packets and do a running mean of each track in the file #what this does do is ASSUME that the input file is 24 bit signed data, otherwise 16 bit would be signed, but 8 bit wouldn't #not that 8 bit is an issue with open(filePath, 'rb') as f: f.seek(chunkPosition) blockWidthInSeconds = 4 samplesToReadBlockSize = (sampleRate * blockWidthInSeconds) numberOfSamplesRemaining = numberOfSamples bufferAmount = samplesToReadBlockSize if numberOfSamples > samplesToReadBlockSize else numberOfSamples totalBlocksInFile = numberOfSamplesRemaining // samplesToReadBlockSize shouldReadEntireFile = False analysisSpacing = 0 numberOfAnalyses = 34 initialAnalyses = 0 if totalBlocksInFile < (2 * numberOfAnalyses): shouldReadEntireFile = True else: analysisSpacing = totalBlocksInFile / numberOfAnalyses startTime = datetime.datetime.now() constantBitDepth16 = pow(2,15) constantBitDepth24 = pow(2,23) #totalsCounter = RunningTotalCounter(pow(2,(bitsPerSample-1)), samplesToReadBlockSize, numberOfChannels) totalsCounter = RunningTotalCounter(constantBitDepth16, samplesToReadBlockSize, numberOfChannels) # you need to constrain the size of the input as we will be calculating RMS values which require exponential math while numberOfSamplesRemaining > 0: #read a buffer's amount of samples if numberOfSamplesRemaining > bufferAmount: bytesToRead = packetByteWidth * bufferAmount data = f.read(bytesToRead) numberOfSamplesRemaining -= (len(data)/packetByteWidth) if len(data) != bytesToRead: logging.error("IO Error: bytes returned do not match bytes asked for") #read a buffer's amount of samples analysis = totalsCounter.emptyAnalysisDictionary() # read the file or current analysis into memory and sum all of the samples and raise to the 2nd pow if shouldReadEntireFile == True or (initialAnalyses % analysisSpacing == 0): for i in range(0, bytesToRead, packetByteWidth): subdata = data[i:(i+packetByteWidth)] for chPos in range(0, numberOfChannels): trackoffset = chPos * channelByteWidth extendedValue = les24toles32Value(''.join(subdata[trackoffset:trackoffset+channelByteWidth])) extendedValue = int(((1.0 * extendedValue) / constantBitDepth24) * constantBitDepth16) analysis[str(chPos)] += (extendedValue**2) totalsCounter.addAnalysis(analysis) initialAnalyses += 1 else: data = f.read(packetByteWidth * numberOfSamplesRemaining) numberOfSamplesRemaining = 0 return totalsCounter.performAnalysis()
def analyzeTrackCorrelations(filePath): wavefile = None if os.path.exists(filePath): wavefile = PCWaveFile(filePath) else: return if wavefile == None or wavefile.isValidWaveFile() == False: return { "status": "fail", "resultString": "file is not a wavefile", "layout": "Unknown" } sampleRate = wavefile.fmtChunkInfoDict['nSamplesPerSec'] channelByteWidth = wavefile.fmtChunkInfoDict['wBitsPerSample'] / 8 bitsPerSample = wavefile.fmtChunkInfoDict['wBitsPerSample'] numberOfChannels = wavefile.fmtChunkInfoDict['nChannels'] packetByteWidth = channelByteWidth * numberOfChannels if numberOfChannels != 6: if numberOfChannels == 2: return { "status": "pass", "resultString": "File contains {} audio channels".format(numberOfChannels), "layout": "STEREO" } else: return { "status": "pass", "resultString": "File contains {} audio channels".format(numberOfChannels), "layout": "Unknown" } isSigned = True if channelByteWidth == 1: isSigned = False chunkPosition = wavefile.getDataChunk()['chunkPosition'] numberOfSamples = wavefile.getDataChunk()['chunkSize'] / packetByteWidth #open the file, read through the packets and do a running mean of each track in the file #what this does do is ASSUME that the input file is 24 bit signed data, otherwise 16 bit would be signed, but 8 bit wouldn't #not that 8 bit is an issue with open(filePath, 'rb') as f: f.seek(chunkPosition) blockWidthInSeconds = 1 samplesToReadBlockSize = (sampleRate * blockWidthInSeconds) / 2 numberOfSamplesRemaining = numberOfSamples bufferAmount = samplesToReadBlockSize if numberOfSamples > samplesToReadBlockSize else numberOfSamples totalBlocksInFile = numberOfSamplesRemaining // samplesToReadBlockSize shouldReadEntireFile = False analysisSpacing = 0 numberOfAnalyses = 34 initialAnalyses = 0 if totalBlocksInFile < (2 * numberOfAnalyses): shouldReadEntireFile = True else: analysisSpacing = totalBlocksInFile / numberOfAnalyses startTime = datetime.datetime.now() constantBitDepth16 = pow(2, 15) constantBitDepth24 = pow(2, 23) #totalsCounter = RunningTotalCounter(pow(2,(bitsPerSample-1)), samplesToReadBlockSize, numberOfChannels) totalsCounter = RunningTotalCounter(constantBitDepth16, samplesToReadBlockSize, numberOfChannels) # you need to constrain the size of the input as we will be calculating RMS values which require exponential math while numberOfSamplesRemaining > 0: #read a buffer's amount of samples if numberOfSamplesRemaining > bufferAmount: bytesToRead = packetByteWidth * bufferAmount data = f.read(bytesToRead) numberOfSamplesRemaining -= (len(data) / packetByteWidth) if len(data) != bytesToRead: logging.error( "IO Error: bytes returned do not match bytes asked for" ) #read a buffer's amount of samples analysis = {} for i in range(0, numberOfChannels): analysis[str(i)] = [] # read the file or current analysis into memory and sum all of the samples and raise to the 2nd pow if shouldReadEntireFile == True or (initialAnalyses % analysisSpacing == 0): for i in range(0, bytesToRead, packetByteWidth): subdata = data[i:(i + packetByteWidth)] for chPos in range(0, numberOfChannels): trackoffset = chPos * channelByteWidth extendedValue = les24toles32Value(''.join( subdata[trackoffset:trackoffset + channelByteWidth])) extendedValue = int( ((1.0 * extendedValue) / constantBitDepth24) * constantBitDepth16) analysis[str(chPos)].append(extendedValue) maxValue = 0 track = 0 srcTrack = '0' for i in [0, 1, 2, 3, 4, 5]: if int(srcTrack) == i: continue result = np.cov(analysis[srcTrack], analysis[str(i)])[0, 1] if result > maxValue: maxValue = result track = i print srcTrack, "matches", track, "with", maxValue initialAnalyses += 1 else: data = f.read(packetByteWidth * numberOfSamplesRemaining) numberOfSamplesRemaining = 0 return {"OK": "OK"}
def analyzeTwoPopInEighths(filePath): if not os.path.exists(filePath): return {"status":"fail", "resultString":"file doesn't exist", "warningString":""} wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: return {"status":"fail", "resultString":"file is not a wavefile"} dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() timeCodeSampleRate = int(math.ceil(sampleRate * 1.001)) byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() data_size = int(math.ceil(sampleRate * 1.001))/24 #1 second of audio dataStartPosOffset = 0 normalizedTimeStamp = wavefile.timestamp # currentPositionInFile = 0 dataLengthInSamples = dataLength / (numberOfChannels * byteWidth) # print "dataStartPosOffset",dataStartPosOffset toneStartTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("00:57:30:00", timeCodeSampleRate, 24) popSafeStartTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("00:59:57:00", timeCodeSampleRate, 24) hourOneTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("01:00:00:00", timeCodeSampleRate, 24) # print "normalizedTimeStamp",normalizedTimeStamp # print "toneStartTimeStamp",toneStartTimeStamp #assume file starts at 00:57:30:00, in the case that the file doesn't have a bext extension #also gets into an issue of what to favor, bext over regn? I assume that the encoders user bext #as you couldn't reliably expect a regn chunk if normalizedTimeStamp == 0 or (normalizedTimeStamp % (timeCodeSampleRate * 60 * 60 * 24) == 0): normalizedTimeStamp = toneStartTimeStamp #we're going to read 3 seconds total secondsInSamplesToRead = 3 * timeCodeSampleRate # print "secondsInSamplesToRead",secondsInSamplesToRead #make sure that the timestamp starts on the second, otherwise normalize the timestamp normalizedTimestampOffset = wavefile.timestamp % timeCodeSampleRate if normalizedTimestampOffset > 0: dataStartPosOffset += (timeCodeSampleRate - normalizedTimestampOffset) * byteWidth * numberOfChannels normalizedTimeStamp = wavefile.timestamp + (timeCodeSampleRate - normalizedTimestampOffset) # print "(timeCodeSampleRate - normalizedTimestampOffset)", (timeCodeSampleRate - normalizedTimestampOffset) # print "normalizedTimestampOffset", normalizedTimestampOffset # print "dataStartPosOffset", dataStartPosOffset # print "normalizedTimeStamp", normalizedTimeStamp if normalizedTimeStamp > popSafeStartTimeStamp: # print 'if wavefile.timestamp > toneStartTimeStamp:' return {"status":"fail", "resultString":"timecode start exceeds pop location","warningString":""} if dataLengthInSamples < (hourOneTimeStamp - toneStartTimeStamp): return {"status":"fail", "resultString":"the file is too short", "warningString":""} if normalizedTimeStamp < popSafeStartTimeStamp: #seek to start time to analyze sampleDifference = (popSafeStartTimeStamp - normalizedTimeStamp) currentPositionInFile = sampleDifference + normalizedTimeStamp dataStartPosOffset += (sampleDifference * byteWidth * numberOfChannels) #lets only look at the 3 seconds of the file from 00:59:57:00 to 01:00:00:00 sizeToRead = secondsInSamplesToRead * byteWidth * numberOfChannels sizeToRead = sizeToRead if dataLength > sizeToRead else dataLength #this scans the head to make sure there is no signal in the head up to a sixteenth of frame before the pop headResult = preScanHead(filePath, data_size, dataStartPos, dataStartPosOffset, byteWidth, numberOfChannels, sampleRate) #this scans the tail to make sure there is no signal in the tail after an eighth of a frame after the pop nextByteOffset = (data_size * 25 * byteWidth * numberOfChannels) #seek 25 frames from the initial start which would be 59:58:01 tailResult = preScanTail(filePath, data_size, dataStartPos, (dataStartPosOffset + nextByteOffset), byteWidth, numberOfChannels, sampleRate) overallResult = {"status":"pass", "resultString":""} suppressSuperfluousWarnings = False if headResult['status'] == 'fail': overallResult['status'] = 'fail' overallResult["resultString"] += headResult["resultString"] if tailResult['status'] == 'fail': overallResult['status'] = 'fail' overallResult["resultString"] += tailResult["resultString"] if overallResult['status'] == 'pass': overallResult["resultString"] = "Pop area contains no discernable problems." twoPopCounter = TwoPopCounterAlt() twoPopCounter.timeCodeSampleRate = timeCodeSampleRate twoPopCounter.timeBase = 24 with open(filePath, 'rb') as f: f.seek(dataStartPos + dataStartPosOffset) dataToReadChunkSize = data_size*byteWidth*numberOfChannels dataRemaining = sizeToRead while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) dataRemaining -= len(data) for channel in range(0, numberOfChannels): subdata = "" for x in range(channel*byteWidth,len(data),byteWidth*numberOfChannels): subdata += (data[x] + data[x+1] + data[x+2]) analysis = ultimateFreqAndPowerForData(subdata, byteWidth, sampleRate) twoPopCounter.addAnalysisForChannelAndTimeStamp(analysis, channel, currentPositionInFile) currentPositionInFile += data_size twoPopResult = twoPopCounter.result() #likely that the pop is off as we are checking an area of up to a sixteenth of frame prior to the pop and area an eighth of a frame #after the pop if overallResult['status'] == 'fail' and twoPopResult['status'] == 'pass': twoPopResult['status'] = 'fail' twoPopResult['resultString'] = "Check your pop as it is likely off. " + overallResult['resultString'] if overallResult['status'] == 'fail' and twoPopResult['status'] == 'fail' and twoPopResult['foundPop'] == 'pass': twoPopResult['status'] = 'fail' twoPopResult['resultString'] = "Check your pop as it is likely off. " + overallResult['resultString'] popIntegrityResult = {"status":"pass", "resultString":""} if overallResult['status'] == 'pass' and twoPopResult['status'] == 'pass' and twoPopResult['foundPop'] == 'pass': #lets make sure the pop actually starts consists of a frame nextByteOffset = (data_size * 23 * byteWidth * numberOfChannels) #seek 23 frames from the initial start which would be 59:57:23 popIntegrityResult = scanPop(filePath, data_size, dataStartPos, (dataStartPosOffset + nextByteOffset), byteWidth, numberOfChannels, sampleRate) if popIntegrityResult['status'] == 'fail': twoPopResult['status'] = 'fail' twoPopResult['resultString'] = popIntegrityResult['resultString'] return twoPopResult
def analyzeTwoPopAlt(filePath): if not os.path.exists(filePath): return {"status":"fail", "resultString":"file doesn't exist", "warningString":""} wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: return {"status":"fail", "resultString":"file is not a wavefile"} dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() timeCodeSampleRate = int(math.ceil(sampleRate * 1.001)) byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() data_size = int(math.ceil(sampleRate * 1.001))/24 #1 second of audio dataStartPosOffset = 0 normalizedTimeStamp = wavefile.timestamp # currentPositionInFile = 0 dataLengthInSamples = dataLength / (numberOfChannels * byteWidth) # print "dataStartPosOffset",dataStartPosOffset toneStartTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("00:57:30:00", timeCodeSampleRate, 24) popSafeStartTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("00:59:57:00", timeCodeSampleRate, 24) hourOneTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("01:00:00:00", timeCodeSampleRate, 24) # print "normalizedTimeStamp",normalizedTimeStamp # print "toneStartTimeStamp",toneStartTimeStamp #assume file starts at 00:57:30:00, in the case that the file doesn't have a bext extension #also gets into an issue of what to favor, bext over regn? I assume that the encoders user bext #as you couldn't reliably expect a regn chunk if normalizedTimeStamp == 0: normalizedTimeStamp = toneStartTimeStamp #we're going to read 3 seconds total secondsInSamplesToRead = 3 * timeCodeSampleRate # print "secondsInSamplesToRead",secondsInSamplesToRead #make sure that the timestamp starts on the second, otherwise normalize the timestamp normalizedTimestampOffset = wavefile.timestamp % timeCodeSampleRate if normalizedTimestampOffset > 0: dataStartPosOffset += (timeCodeSampleRate - normalizedTimestampOffset) * byteWidth * numberOfChannels normalizedTimeStamp = wavefile.timestamp + (timeCodeSampleRate - normalizedTimestampOffset) # print "(timeCodeSampleRate - normalizedTimestampOffset)", (timeCodeSampleRate - normalizedTimestampOffset) # print "normalizedTimestampOffset", normalizedTimestampOffset # print "dataStartPosOffset", dataStartPosOffset # print "normalizedTimeStamp", normalizedTimeStamp if normalizedTimeStamp > popSafeStartTimeStamp: # print 'if wavefile.timestamp > toneStartTimeStamp:' return {"status":"fail", "resultString":"timecode start exceeds pop location","warningString":""} if dataLengthInSamples < (hourOneTimeStamp - toneStartTimeStamp): return {"status":"fail", "resultString":"the file is too short", "warningString":""} if normalizedTimeStamp < popSafeStartTimeStamp: # print 'if wavefile.timestamp < toneStartTimeStamp:' sampleDifference = (popSafeStartTimeStamp - normalizedTimeStamp) currentPositionInFile = sampleDifference + normalizedTimeStamp dataStartPosOffset += (sampleDifference * byteWidth * numberOfChannels) #lets only look at the 3 seconds of the file from 00:59:57:00 to 01:00:00:00 sizeToRead = secondsInSamplesToRead * byteWidth * numberOfChannels sizeToRead = sizeToRead if dataLength > sizeToRead else dataLength # print "sizeToRead",sizeToRead with open(filePath, 'rb') as f: f.seek(dataStartPos + dataStartPosOffset) dataToReadChunkSize = data_size*byteWidth*numberOfChannels dataRemaining = sizeToRead twoPopCounter = TwoPopCounterAlt() twoPopCounter.timeCodeSampleRate = timeCodeSampleRate twoPopCounter.timeBase = 24 while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) dataRemaining -= len(data) for channel in range(0, numberOfChannels): subdata = "" for x in range(channel*byteWidth,len(data),byteWidth*numberOfChannels): subdata += (data[x] + data[x+1] + data[x+2]) analysis = ultimateFreqAndPowerForData(subdata, byteWidth, sampleRate) twoPopCounter.addAnalysisForChannelAndTimeStamp(analysis, channel, currentPositionInFile) currentPositionInFile += data_size return twoPopCounter.result()
def analyzeHeadAlt(filePath): if os.path.exists(filePath): wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: return {"status":"fail", "resultString":"file is not a wavefile"} dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() timeCodeSampleRate = int(math.ceil(sampleRate * 1.001)) byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() data_size = int(math.ceil(sampleRate * 1.001)) #1 second of audio dataLengthInSamples = dataLength / (numberOfChannels * byteWidth) dataStartPosOffset = 0 normalizedTimeStamp = wavefile.timestamp # # print "dataStartPosOffset",dataStartPosOffset toneStartTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("00:57:30:00", timeCodeSampleRate, 24) # print "normalizedTimeStamp",normalizedTimeStamp # print "toneStartTimeStamp",toneStartTimeStamp #assume file starts at 00:57:30:00, in the case that the file doesn't have a bext extension #also gets into an issue of what to favor, bext over regn? I assume that the encoders user bext #as you couldn't reliably expect a regn chunk if normalizedTimeStamp == 0 or (normalizedTimeStamp % (timeCodeSampleRate * 60 * 60 * 24) == 0) : normalizedTimeStamp = toneStartTimeStamp #the head length should be 150 seconds secondsInSamplesToRead = 150 * timeCodeSampleRate # print "secondsInSamplesToRead",secondsInSamplesToRead if secondsInSamplesToRead > dataLengthInSamples: return {"status":"fail", "resultString":"the file is too short", "warningString":""} #make sure that the timestamp starts on the second, otherwise normalize the timestamp normalizedTimestampOffset = wavefile.timestamp % timeCodeSampleRate if normalizedTimestampOffset > 0: dataStartPosOffset += (timeCodeSampleRate - normalizedTimestampOffset) * byteWidth * numberOfChannels normalizedTimeStamp = wavefile.timestamp + (timeCodeSampleRate - normalizedTimestampOffset) # print "(timeCodeSampleRate - normalizedTimestampOffset)", (timeCodeSampleRate - normalizedTimestampOffset) # print "normalizedTimestampOffset", normalizedTimestampOffset # print "dataStartPosOffset", dataStartPosOffset # print "normalizedTimeStamp", normalizedTimeStamp if normalizedTimeStamp > toneStartTimeStamp: # print 'if wavefile.timestamp > toneStartTimeStamp:' secondsInSamplesToRead -= (normalizedTimeStamp - toneStartTimeStamp) if normalizedTimeStamp < toneStartTimeStamp: # print 'if wavefile.timestamp < toneStartTimeStamp:' secondsInSamplesToRead += (toneStartTimeStamp - normalizedTimeStamp) #lets only look at the first 150 seconds of the file sizeToRead = secondsInSamplesToRead * byteWidth * numberOfChannels sizeToRead = sizeToRead if dataLength > sizeToRead else dataLength second = 0 with open(filePath, 'rb') as f: startTime = datetime.datetime.now() dataStartPos += dataStartPosOffset f.seek(dataStartPos) dataToReadChunkSize = timeCodeSampleRate*byteWidth*numberOfChannels dataRemaining = sizeToRead counterDict = {} for channel in range(0, numberOfChannels): counterDict[str(channel)] = ToneCounterAlt() while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) dataRemaining -= len(data) currentPositionInFile = normalizedTimeStamp + (second * data_size) # print currentPositionInFile, pctimecode.convertUnsignedLongLongToTimeCode(currentPositionInFile, 48048, 24) for channel in range(0, numberOfChannels): subdata = "" for x in range(channel*byteWidth,len(data),byteWidth*numberOfChannels): subdata += (data[x] + data[x+1] + data[x+2]) result = highestAndNextHighestFreqAndPowerForData(subdata, byteWidth, sampleRate) toneCounter = counterDict[str(channel)] toneCounter.addAnalysis({ "currentTimeStamp":currentPositionInFile, "timeCodeSampleRate":timeCodeSampleRate, "freqs":result, "RMSForInputData":calculateRMSForData(subdata, byteWidth)}) second += 1 #Questions to answer 1) Does it have at least 60 secs of tone 2) Does it start at head 3) Does it have a Pop 4) Does it have other tones? toneCounterResult = ToneCounterResultAlt(timeCodeSampleRate, 24) return toneCounterResult.result(counterDict) else: return {"status":"fail", "resultString":"file doesn't exist","warningString":""}