Sélectionner une révision Git
AudioVisualizer.cc 2,63 Kio
#include "AudioVisualizer.hh"
#include "../../Lib/Audio.hh"
using namespace Vivy;
#define MAXPIXVALUE 7 // Some magix AV magic stuff
AudioVisualizer::AudioVisualizer(AudioContext::StreamPtr stream, QWidget *parent)
: QWidget(parent)
{
if (!stream->isDecoded()) {
stream->decodeData();
}
double *decodedData = stream->getDecodedData();
if (decodedData == nullptr)
throw std::logic_error("the passed stream is not decoded");
const size_t size = stream->getDecodedDataSize();
const size_t height = stream->getDecodedChunkSize();
const size_t decalage = stream->getDecodedDecalage();
const size_t width = (size - height) / decalage;
uchar *pixels = new uchar[static_cast<size_t>(width * height / 2)]();
FFTSamplePtr chunkData(
reinterpret_cast<FFTSample *>(av_malloc_array(2 * height, sizeof(FFTSample))),
fftSampleDeleter);
RDFTContextPtr ctx(av_rdft_init((static_cast<int>(log2(static_cast<int>(height)))), DFT_R2C),
rdftContextDeleter);
if (!(chunkData && ctx)) {
delete[] pixels;
throw std::runtime_error("out of memory");
}
/* Compute the image data */
for (size_t x = 0, i = 0; i < size - height; i += decalage, ++x) {
parallel_for (size_t j = 0; j < height; j++) {
const double curr_dat = decodedData[i + j];
const double window_modifier =
(1 - cos(2 * M_PI * static_cast<double>(j) / static_cast<double>(height - 1))) / 2;
const float value =
std::clamp(static_cast<float>(window_modifier * curr_dat), -1.0f, 1.0f);
chunkData[j] = value;
}
av_rdft_calc(ctx.get(), chunkData.get());
parallel_for (size_t j = 0; j < height / 2; j++) {
const float im = chunkData[j * 2];
const float re = chunkData[j * 2 + 1];
const float mag = sqrtf(im * im + re * re);
const size_t index = static_cast<size_t>(j * static_cast<ulong>(width) + x);
pixels[index] = static_cast<unsigned char>((mag)*MAXPIXVALUE);
}
}
QImage img = QImage(pixels, static_cast<int>(width), static_cast<int>(height / 2),
static_cast<int>(width), QImage::Format_Grayscale8, pixelsDeleter, pixels)
.mirrored(false, true);
printSpectrum(img, stream->getDuration());
}
void
AudioVisualizer::printSpectrum(QImage pixmap, qreal audioLength) noexcept
{
TimingView *timer = new TimingView(pixmap, audioLength, this);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(timer);
setLayout(layout);
}