forked from mia/Aegisub
Made most audio spectrum related code multithreaded (automatic number of threads, based on CPU count)
Changed palette for spectrum Originally committed to SVN as r529.
This commit is contained in:
parent
deea37e0ba
commit
29961a029e
2 changed files with 148 additions and 15 deletions
|
@ -37,6 +37,8 @@
|
||||||
///////////
|
///////////
|
||||||
// Headers
|
// Headers
|
||||||
#include <wx/tglbtn.h>
|
#include <wx/tglbtn.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <vector>
|
||||||
#include "audio_display.h"
|
#include "audio_display.h"
|
||||||
#include "audio_provider_stream.h"
|
#include "audio_provider_stream.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
@ -486,6 +488,106 @@ static unsigned short spectrumColorMap16[256];
|
||||||
static bool colorMapsGenerated = false;
|
static bool colorMapsGenerated = false;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// Spectrum analyser rendering thread
|
||||||
|
class SpectrumRendererThread : public wxThread {
|
||||||
|
public:
|
||||||
|
SpectrumRendererThread() : wxThread(wxTHREAD_JOINABLE) {
|
||||||
|
if (Create() != wxTHREAD_NO_ERROR)
|
||||||
|
throw _T("Error creating Spectrum rendering thread.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int *data; // image data to write to (shared)
|
||||||
|
int window; // 1 << Options.AsInt(_T("Audio Spectrum Window"))
|
||||||
|
int firstbar, lastbar; // first and last vertical bar to draw
|
||||||
|
int w, h; // width and height of canvas
|
||||||
|
int cutoff; // cutoff frequency
|
||||||
|
float *base_in; // audio sample data (shared)
|
||||||
|
int samples; // number of samples per column
|
||||||
|
int depth; // display bit depth
|
||||||
|
float scale; // vertical scale of display
|
||||||
|
|
||||||
|
protected:
|
||||||
|
wxThread::ExitCode Entry() {
|
||||||
|
// Pointers to image data
|
||||||
|
int *write_ptr = data;
|
||||||
|
unsigned short *write_ptr16 = (unsigned short *)data;
|
||||||
|
|
||||||
|
// FFT output data
|
||||||
|
float *out_r = new float[window];
|
||||||
|
float *out_i = new float[window];
|
||||||
|
|
||||||
|
// Prepare constants
|
||||||
|
const int halfwindow = window/2;
|
||||||
|
const int posThres = MAX(1,int(double(halfwindow-cutoff)/double(h)*0.5/scale + 0.5));
|
||||||
|
const float mult = float(h)/float(halfwindow-cutoff)/255.f;
|
||||||
|
|
||||||
|
// Calculation loop
|
||||||
|
for (int i = firstbar; i < lastbar; i++) {
|
||||||
|
__int64 curStart = i*samples-(window/2);
|
||||||
|
if (curStart < 0) curStart = 0;
|
||||||
|
|
||||||
|
// Position input
|
||||||
|
float *in = base_in + curStart;
|
||||||
|
|
||||||
|
// Perform the FFT
|
||||||
|
FFT fft;
|
||||||
|
fft.Transform(window,in,out_r,out_i);
|
||||||
|
|
||||||
|
// Draw bar
|
||||||
|
float accum = 0;
|
||||||
|
int accumPos = posThres;
|
||||||
|
int y = h;
|
||||||
|
int intensity;
|
||||||
|
float t1,t2;
|
||||||
|
|
||||||
|
// Position pointer
|
||||||
|
write_ptr = data+i+h*w;
|
||||||
|
write_ptr16 = ((unsigned short*)data)+(i+h*w);
|
||||||
|
|
||||||
|
// Draw loop
|
||||||
|
for (int j=cutoff;j<halfwindow;j++) {
|
||||||
|
// Calculate magnitude and add to accumulator
|
||||||
|
t1 = out_r[j];
|
||||||
|
t1 *= t1;
|
||||||
|
t2 = out_i[j];
|
||||||
|
t2 *= t2;
|
||||||
|
t2 += t1;
|
||||||
|
accum += sqrt(t2);
|
||||||
|
|
||||||
|
// When accumulator goes over, plot point
|
||||||
|
accumPos--;
|
||||||
|
if (accumPos == 0) {
|
||||||
|
intensity = int(accum*mult);
|
||||||
|
if (intensity > 255) intensity = 255;
|
||||||
|
if (intensity < 0) intensity = 0;
|
||||||
|
|
||||||
|
// Write and go to next row
|
||||||
|
if (depth == 32) {
|
||||||
|
write_ptr -= w;
|
||||||
|
*write_ptr = spectrumColorMap[intensity];
|
||||||
|
}
|
||||||
|
else if (depth == 16) {
|
||||||
|
write_ptr16 -= w;
|
||||||
|
*write_ptr16 = spectrumColorMap16[intensity];
|
||||||
|
}
|
||||||
|
|
||||||
|
y--;
|
||||||
|
if (y == 0) break;
|
||||||
|
accumPos = posThres;
|
||||||
|
accum = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete out_r;
|
||||||
|
delete out_i;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
// Draw spectrum analyzer
|
// Draw spectrum analyzer
|
||||||
void AudioDisplay::DrawSpectrum(wxDC &finaldc,bool weak) {
|
void AudioDisplay::DrawSpectrum(wxDC &finaldc,bool weak) {
|
||||||
|
@ -498,14 +600,11 @@ void AudioDisplay::DrawSpectrum(wxDC &finaldc,bool weak) {
|
||||||
|
|
||||||
if (!weak) {
|
if (!weak) {
|
||||||
// Generate colors
|
// Generate colors
|
||||||
//int colorMap[256];
|
|
||||||
//unsigned short colorMap16[256];
|
|
||||||
if (!colorMapsGenerated) {
|
if (!colorMapsGenerated) {
|
||||||
unsigned char r,g,b;
|
unsigned char r,g,b;
|
||||||
for (int i=0;i<256;i++) {
|
for (int i=0;i<256;i++) {
|
||||||
//HSVtoRGB(255-i,1.0f - 0.3f*(i/255.0f),0.3f + 0.7f*(i/255.0f),r,g,b);
|
//hsv_to_rgb(255 - i, 255 - i * 3/10, 255*3/10 + i * 7/10, &r, &g, &b);
|
||||||
//hsv_to_rgb(255-i, 1.0f - 0.3f * (i/255.0f), 0.3f + 0.7f * (i/255.0f), &r, &g, &b);
|
hsl_to_rgb(170 + i * 2/3, 128 + i/2, i, &r, &g, &b);
|
||||||
hsv_to_rgb(255 - i, 255 - i * 3/10, 255*3/10 + i * 7/10, &r, &g, &b);
|
|
||||||
spectrumColorMap[i] = b | (g<<8) | (r<<16);
|
spectrumColorMap[i] = b | (g<<8) | (r<<16);
|
||||||
spectrumColorMap16[i] = ((r>>3)<<11) | ((g>>2)<<5) | b>>3;
|
spectrumColorMap16[i] = ((r>>3)<<11) | ((g>>2)<<5) | b>>3;
|
||||||
}
|
}
|
||||||
|
@ -529,20 +628,52 @@ void AudioDisplay::DrawSpectrum(wxDC &finaldc,bool weak) {
|
||||||
}
|
}
|
||||||
delete raw_int;
|
delete raw_int;
|
||||||
|
|
||||||
// More arrays
|
// For image data
|
||||||
float *out_r = new float[window];
|
|
||||||
float *out_i = new float[window];
|
|
||||||
int *data = new int[w*h*depth/32];
|
int *data = new int[w*h*depth/32];
|
||||||
|
|
||||||
|
////// START OF PARALLELISED CODE //////
|
||||||
|
const int cpu_count = wxThread::GetCPUCount();
|
||||||
|
std::vector<SpectrumRendererThread*> threads(cpu_count);
|
||||||
|
for (int i = 0; i < cpu_count; i++) {
|
||||||
|
// Ugh, way too many data to copy in
|
||||||
|
threads[i] = new SpectrumRendererThread();
|
||||||
|
threads[i]->data = data;
|
||||||
|
threads[i]->window = window;
|
||||||
|
threads[i]->firstbar = i * w/cpu_count;
|
||||||
|
threads[i]->lastbar = (i+1) * w/cpu_count;
|
||||||
|
threads[i]->w = w;
|
||||||
|
threads[i]->h = h;
|
||||||
|
threads[i]->cutoff = cutOff;
|
||||||
|
threads[i]->base_in = raw_float;
|
||||||
|
threads[i]->samples = samples;
|
||||||
|
threads[i]->depth = depth;
|
||||||
|
threads[i]->scale = scale;
|
||||||
|
threads[i]->Run();
|
||||||
|
}
|
||||||
|
// Threads started, wait for them to end
|
||||||
|
for (int i = 0; i < cpu_count; i++) {
|
||||||
|
threads[i]->Wait();
|
||||||
|
delete threads[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional constants
|
||||||
|
const int halfwindow = window/2;
|
||||||
|
const int posThres = MAX(1,int(double(halfwindow-cutOff)/double(h)*0.5/scale + 0.5));
|
||||||
|
const float mult = float(h)/float(halfwindow-cutOff)/255.f;
|
||||||
|
// And more
|
||||||
int *write_ptr = data;
|
int *write_ptr = data;
|
||||||
unsigned short *write_ptr16 = (unsigned short *)data;
|
unsigned short *write_ptr16 = (unsigned short *)data;
|
||||||
|
|
||||||
// Copy to spectrum bitmap
|
/*// More arrays
|
||||||
//dc.BeginDrawing();
|
float *out_r = new float[window];
|
||||||
|
float *out_i = new float[window];
|
||||||
|
int *write_ptr = data;
|
||||||
|
unsigned short *write_ptr16 = (unsigned short *)data;
|
||||||
|
|
||||||
// Prepare variables
|
// Prepare variables
|
||||||
int halfwindow = window/2;
|
int halfwindow = window/2;
|
||||||
int posThres = MAX(1,int(double(halfwindow-cutOff)/double(h)*0.5/scale + 0.5));
|
int posThres = MAX(1,int(double(halfwindow-cutOff)/double(h)*0.5/scale + 0.5));
|
||||||
float mult = float(h)/float(halfwindow-cutOff)/255.0f;
|
float mult = float(h)/float(halfwindow-cutOff)/255.f;
|
||||||
|
|
||||||
// Calculation loop
|
// Calculation loop
|
||||||
for (int i=0;i<w;i++) {
|
for (int i=0;i<w;i++) {
|
||||||
|
@ -603,7 +734,8 @@ void AudioDisplay::DrawSpectrum(wxDC &finaldc,bool weak) {
|
||||||
accum = 0;
|
accum = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
////// END OF PARALLELISED CODE //////
|
||||||
|
|
||||||
// Clear top of image
|
// Clear top of image
|
||||||
int filly = h - (halfwindow-cutOff)/posThres;
|
int filly = h - (halfwindow-cutOff)/posThres;
|
||||||
|
@ -630,8 +762,6 @@ void AudioDisplay::DrawSpectrum(wxDC &finaldc,bool weak) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear memory
|
// Clear memory
|
||||||
delete out_r;
|
|
||||||
delete out_i;
|
|
||||||
delete raw_float;
|
delete raw_float;
|
||||||
|
|
||||||
// Create image
|
// Create image
|
||||||
|
|
|
@ -3,7 +3,10 @@ Please visit http://aegisub.net to download latest version
|
||||||
|
|
||||||
= 1.11 beta - 2006.xx.xx ===========================
|
= 1.11 beta - 2006.xx.xx ===========================
|
||||||
|
|
||||||
- Fixed loading of sections with unexpected cases.
|
- Support reading SSA/ASS files with intermixed V4 and V4+ Styles sections (jfs)
|
||||||
|
- Fixed loading of sections with unexpected cases. (AMZ)
|
||||||
|
- Made Audio Spectrum calculation/drawing code use multithreading, resulting in a significant speedup on SMP (eg. dual-core) systems (jfs)
|
||||||
|
- Changed palette for audio spectrum (jfs)
|
||||||
|
|
||||||
|
|
||||||
= 1.10 beta - 2006.08.07 ===========================
|
= 1.10 beta - 2006.08.07 ===========================
|
||||||
|
|
Loading…
Reference in a new issue