2017-05-28 07:34:34 -04:00
|
|
|
import numpy
|
|
|
|
from PIL import Image, ImageDraw
|
2017-05-28 14:19:28 -04:00
|
|
|
from PyQt4 import uic, QtGui
|
|
|
|
from PyQt4.QtGui import QColor
|
2017-06-06 11:14:39 -04:00
|
|
|
import os
|
|
|
|
import random
|
2017-05-29 20:39:11 -04:00
|
|
|
from . import __base__
|
2017-06-01 10:52:40 -04:00
|
|
|
import time
|
|
|
|
from copy import copy
|
2017-05-28 07:34:34 -04:00
|
|
|
|
|
|
|
|
2017-05-29 20:39:11 -04:00
|
|
|
class Component(__base__.Component):
|
|
|
|
'''Original Audio Visualization'''
|
2017-05-28 14:19:28 -04:00
|
|
|
def widget(self, parent):
|
2017-05-28 07:34:34 -04:00
|
|
|
self.parent = parent
|
2017-06-06 11:14:39 -04:00
|
|
|
self.visColor = (255, 255, 255)
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-06 11:14:39 -04:00
|
|
|
page = uic.loadUi(os.path.join(
|
|
|
|
os.path.dirname(os.path.realpath(__file__)), 'original.ui'))
|
2017-05-28 07:34:34 -04:00
|
|
|
page.comboBox_visLayout.addItem("Classic")
|
|
|
|
page.comboBox_visLayout.addItem("Split")
|
|
|
|
page.comboBox_visLayout.addItem("Bottom")
|
|
|
|
page.comboBox_visLayout.setCurrentIndex(0)
|
|
|
|
page.comboBox_visLayout.currentIndexChanged.connect(self.update)
|
2017-05-28 14:19:28 -04:00
|
|
|
page.lineEdit_visColor.setText('%s,%s,%s' % self.visColor)
|
|
|
|
page.pushButton_visColor.clicked.connect(lambda: self.pickColor())
|
2017-06-06 11:14:39 -04:00
|
|
|
btnStyle = "QPushButton { background-color : %s; outline: none; }" \
|
|
|
|
% QColor(*self.visColor).name()
|
2017-05-28 14:19:28 -04:00
|
|
|
page.pushButton_visColor.setStyleSheet(btnStyle)
|
|
|
|
page.lineEdit_visColor.textChanged.connect(self.update)
|
|
|
|
self.page = page
|
2017-06-02 01:30:44 -04:00
|
|
|
self.canceled = False
|
2017-05-28 07:34:34 -04:00
|
|
|
return page
|
2017-06-06 11:14:39 -04:00
|
|
|
|
2017-05-28 07:34:34 -04:00
|
|
|
def update(self):
|
|
|
|
self.layout = self.page.comboBox_visLayout.currentIndex()
|
2017-05-29 20:39:11 -04:00
|
|
|
self.visColor = self.RGBFromString(self.page.lineEdit_visColor.text())
|
2017-05-28 07:34:34 -04:00
|
|
|
self.parent.drawPreview()
|
|
|
|
|
2017-05-30 22:05:56 -04:00
|
|
|
def loadPreset(self, pr):
|
|
|
|
self.page.lineEdit_visColor.setText('%s,%s,%s' % pr['visColor'])
|
2017-06-06 11:14:39 -04:00
|
|
|
btnStyle = "QPushButton { background-color : %s; outline: none; }" \
|
|
|
|
% QColor(*pr['visColor']).name()
|
2017-05-30 22:05:56 -04:00
|
|
|
self.page.pushButton_visColor.setStyleSheet(btnStyle)
|
|
|
|
self.page.comboBox_visLayout.setCurrentIndex(pr['layout'])
|
2017-06-06 11:14:39 -04:00
|
|
|
|
2017-05-28 21:24:51 -04:00
|
|
|
def savePreset(self):
|
2017-06-06 11:14:39 -04:00
|
|
|
return {
|
|
|
|
'layout': self.layout,
|
|
|
|
'visColor': self.visColor,
|
|
|
|
}
|
2017-05-28 21:24:51 -04:00
|
|
|
|
2017-05-28 14:19:28 -04:00
|
|
|
def previewRender(self, previewWorker):
|
2017-06-06 11:14:39 -04:00
|
|
|
spectrum = numpy.fromfunction(
|
|
|
|
lambda x: 0.008*(x-128)**2, (255,), dtype="int16")
|
2017-05-28 07:34:34 -04:00
|
|
|
width = int(previewWorker.core.settings.value('outputWidth'))
|
|
|
|
height = int(previewWorker.core.settings.value('outputHeight'))
|
2017-06-06 11:14:39 -04:00
|
|
|
return self.drawBars(
|
|
|
|
width, height, spectrum, self.visColor, self.layout)
|
|
|
|
|
2017-05-28 07:34:34 -04:00
|
|
|
def preFrameRender(self, **kwargs):
|
2017-05-29 20:39:11 -04:00
|
|
|
super().preFrameRender(**kwargs)
|
2017-05-28 07:34:34 -04:00
|
|
|
self.smoothConstantDown = 0.08
|
|
|
|
self.smoothConstantUp = 0.8
|
|
|
|
self.lastSpectrum = None
|
2017-05-31 03:15:09 -04:00
|
|
|
self.spectrumArray = {}
|
2017-06-04 13:00:36 -04:00
|
|
|
self.width = int(self.worker.core.settings.value('outputWidth'))
|
|
|
|
self.height = int(self.worker.core.settings.value('outputHeight'))
|
2017-05-31 03:15:09 -04:00
|
|
|
|
|
|
|
for i in range(0, len(self.completeAudioArray), self.sampleSize):
|
2017-06-02 01:30:44 -04:00
|
|
|
if self.canceled:
|
|
|
|
break
|
2017-06-06 11:14:39 -04:00
|
|
|
self.lastSpectrum = self.transformData(
|
|
|
|
i, self.completeAudioArray, self.sampleSize,
|
|
|
|
self.smoothConstantDown, self.smoothConstantUp,
|
|
|
|
self.lastSpectrum)
|
2017-06-01 10:52:40 -04:00
|
|
|
self.spectrumArray[i] = copy(self.lastSpectrum)
|
2017-05-31 03:15:09 -04:00
|
|
|
|
2017-06-02 04:30:51 -04:00
|
|
|
progress = int(100*(i/len(self.completeAudioArray)))
|
|
|
|
if progress >= 100:
|
|
|
|
progress = 100
|
2017-06-06 11:14:39 -04:00
|
|
|
pStr = "Analyzing audio: "+str(progress)+'%'
|
2017-06-02 04:30:51 -04:00
|
|
|
self.progressBarSetText.emit(pStr)
|
|
|
|
self.progressBarUpdate.emit(int(progress))
|
2017-06-06 11:14:39 -04:00
|
|
|
|
2017-06-04 13:00:36 -04:00
|
|
|
def frameRender(self, moduleNo, arrayNo, frameNo):
|
2017-06-06 11:14:39 -04:00
|
|
|
return self.drawBars(
|
|
|
|
self.width, self.height,
|
|
|
|
self.spectrumArray[arrayNo],
|
|
|
|
self.visColor, self.layout)
|
2017-05-28 14:19:28 -04:00
|
|
|
|
|
|
|
def pickColor(self):
|
2017-05-29 20:39:11 -04:00
|
|
|
RGBstring, btnStyle = super().pickColor()
|
2017-05-30 22:05:56 -04:00
|
|
|
if not RGBstring:
|
|
|
|
return
|
2017-05-29 20:39:11 -04:00
|
|
|
self.page.lineEdit_visColor.setText(RGBstring)
|
|
|
|
self.page.pushButton_visColor.setStyleSheet(btnStyle)
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-06 11:14:39 -04:00
|
|
|
def transformData(
|
|
|
|
self, i, completeAudioArray, sampleSize,
|
|
|
|
smoothConstantDown, smoothConstantUp, lastSpectrum):
|
2017-06-01 10:52:40 -04:00
|
|
|
if len(completeAudioArray) < (i + sampleSize):
|
|
|
|
sampleSize = len(completeAudioArray) - i
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 10:52:40 -04:00
|
|
|
window = numpy.hanning(sampleSize)
|
|
|
|
data = completeAudioArray[i:i+sampleSize][::1] * window
|
|
|
|
paddedSampleSize = 2048
|
2017-06-06 11:14:39 -04:00
|
|
|
paddedData = numpy.pad(
|
|
|
|
data, (0, paddedSampleSize - sampleSize), 'constant')
|
2017-06-01 10:52:40 -04:00
|
|
|
spectrum = numpy.fft.fft(paddedData)
|
|
|
|
sample_rate = 44100
|
|
|
|
frequencies = numpy.fft.fftfreq(len(spectrum), 1./sample_rate)
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 10:52:40 -04:00
|
|
|
y = abs(spectrum[0:int(paddedSampleSize/2) - 1])
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 10:52:40 -04:00
|
|
|
# filter the noise away
|
|
|
|
# y[y<80] = 0
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 10:52:40 -04:00
|
|
|
y = 20 * numpy.log10(y)
|
|
|
|
y[numpy.isinf(y)] = 0
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 10:52:40 -04:00
|
|
|
if lastSpectrum is not None:
|
2017-06-06 11:14:39 -04:00
|
|
|
lastSpectrum[y < lastSpectrum] = \
|
|
|
|
y[y < lastSpectrum] * smoothConstantDown + \
|
|
|
|
lastSpectrum[y < lastSpectrum] * (1 - smoothConstantDown)
|
|
|
|
|
|
|
|
lastSpectrum[y >= lastSpectrum] = \
|
|
|
|
y[y >= lastSpectrum] * smoothConstantUp + \
|
|
|
|
lastSpectrum[y >= lastSpectrum] * (1 - smoothConstantUp)
|
2017-06-01 10:52:40 -04:00
|
|
|
else:
|
|
|
|
lastSpectrum = y
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 10:52:40 -04:00
|
|
|
x = frequencies[0:int(paddedSampleSize/2) - 1]
|
|
|
|
|
|
|
|
return lastSpectrum
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 12:01:51 -04:00
|
|
|
def drawBars(self, width, height, spectrum, color, layout):
|
|
|
|
vH = height-height/8
|
|
|
|
bF = width / 64
|
|
|
|
bH = bF / 2
|
|
|
|
bQ = bF / 4
|
2017-06-06 11:14:39 -04:00
|
|
|
imTop = Image.new("RGBA", (width, height), (0, 0, 0, 0))
|
2017-06-01 12:01:51 -04:00
|
|
|
draw = ImageDraw.Draw(imTop)
|
|
|
|
r, g, b = color
|
|
|
|
color2 = (r, g, b, 125)
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 12:01:51 -04:00
|
|
|
bP = height / 1200
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 12:01:51 -04:00
|
|
|
for j in range(0, 63):
|
2017-06-06 11:14:39 -04:00
|
|
|
draw.rectangle((
|
|
|
|
bH + j * bF, vH+bQ, bH + j * bF + bF, vH + bQ -
|
|
|
|
spectrum[j * 4] * bP - bH), fill=color2)
|
|
|
|
|
|
|
|
draw.rectangle((
|
|
|
|
bH + bQ + j * bF, vH, bH + bQ + j * bF + bH, vH -
|
|
|
|
spectrum[j * 4] * bP), fill=color)
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 12:01:51 -04:00
|
|
|
imBottom = imTop.transpose(Image.FLIP_TOP_BOTTOM)
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-06 11:14:39 -04:00
|
|
|
im = Image.new("RGBA", (width, height), (0, 0, 0, 0))
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 12:01:51 -04:00
|
|
|
if layout == 0:
|
|
|
|
y = 0 - int(height/100*43)
|
|
|
|
im.paste(imTop, (0, y), mask=imTop)
|
|
|
|
y = 0 + int(height/100*43)
|
|
|
|
im.paste(imBottom, (0, y), mask=imBottom)
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 12:01:51 -04:00
|
|
|
if layout == 1:
|
|
|
|
y = 0 + int(height/100*10)
|
|
|
|
im.paste(imTop, (0, y), mask=imTop)
|
|
|
|
y = 0 - int(height/100*10)
|
|
|
|
im.paste(imBottom, (0, y), mask=imBottom)
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 12:01:51 -04:00
|
|
|
if layout == 2:
|
|
|
|
y = 0 + int(height/100*10)
|
|
|
|
im.paste(imTop, (0, y), mask=imTop)
|
2017-05-28 07:34:34 -04:00
|
|
|
|
2017-06-01 12:01:51 -04:00
|
|
|
return im
|
2017-06-02 01:30:44 -04:00
|
|
|
|