#!/usr/bin/env python3 import wave class WaveLoader: def __init__(self, filename): self.soundfile = wave.open(filename, 'rb') self.channels = self.soundfile.getnchannels() self.sampleWidth = self.soundfile.getsampwidth() self.frameCount = self.soundfile.getnframes() self.frameRate = self.soundfile.getframerate() self.filename = filename self.amplitudeMax = 2 ** (self.sampleWidth * 8) self.levelData = {} self.amplitudeData = {} def __del__(self): self.soundfile.close() def getCurrentLevelRealtime(self, seconds): frameIndex = int(round(seconds * self.frameRate)) if frameIndex >= self.frameCount: return 0 self.soundfile.setpos(frameIndex) level = int.from_bytes(self.soundfile.readframes(1)[0:self.sampleWidth], 'little') if level > self.amplitudeMax * 0.5: level -= self.amplitudeMax return abs(level) / (self.amplitudeMax * 0.5) def getLevel(self, channel = 0): if channel < self.channels: return self.levelData[channel].copy() def getAmplitude(self, channel = 0): if channel < self.channels: return self.amplitudeData[channel].copy() def getLevelSum(self): if self.channels == 1: return self.levelData[0].copy() levelSum = [] for f in range(self.frameCount): amplitudeSum = 0 for c in range(self.channels): amplitudeSum += self.levelData[c][f] levelSum.append(amplitudeSum / self.channels) return levelSum def getCurrentLevel(self, seconds): frameIndex = int(round(seconds * self.frameRate)) if frameIndex >= self.frameCount: return 0 level = self.levelData[0][frameIndex] return level level = 0 for c in range(self.channels): level += self.levelData[c][frameIndex] return level / self.channels def loadData(self): self.levelReset() self.amplitudeReset() soundfile = wave.open(self.filename, 'rb') for f in range(self.frameCount): frame = soundfile.readframes(1) for c in range(self.channels): byteOffset = c * self.sampleWidth amplitude = int.from_bytes(frame[byteOffset:byteOffset + self.sampleWidth], 'little') if amplitude > self.amplitudeMax * 0.5: amplitude -= self.amplitudeMax self.amplitudeData[c].append(amplitude / (self.amplitudeMax * 0.5)) self.levelData[c].append(abs(amplitude) / (self.amplitudeMax * 0.5)) soundfile.close() def levelReset(self): self.levelData = {} for c in range(self.channels): self.levelData[c] = [] def amplitudeReset(self): self.amplitudeData = {} for c in range(self.channels): self.amplitudeData[c] = []