pumpkin/waveloader.py

108 lines
2.5 KiB
Python

#!/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] = []