X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fplugins%2Fspectrogram%2Fspectrogram.C;fp=cinelerra-5.1%2Fplugins%2Fspectrogram%2Fspectrogram.C;h=47825309dfb8426ec723f9fa3d6de7036b1ca89f;hp=15730e646ce42619df170a07b4a219a7630e620a;hb=033efab12586e8086014c814a5360f211d228ac3;hpb=0e6cf5b52d1ebce9272270144bcf43df4683507e diff --git a/cinelerra-5.1/plugins/spectrogram/spectrogram.C b/cinelerra-5.1/plugins/spectrogram/spectrogram.C index 15730e64..47825309 100644 --- a/cinelerra-5.1/plugins/spectrogram/spectrogram.C +++ b/cinelerra-5.1/plugins/spectrogram/spectrogram.C @@ -1,7 +1,6 @@ - /* * CINELERRA - * Copyright (C) 1997-2011 Adam Williams + * Copyright (C) 1997-2019 Adam Williams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -92,10 +91,11 @@ void SpectrogramConfig::interpolate(SpectrogramConfig &prev, SpectrogramFrame::SpectrogramFrame(int data_size) + : PluginClientFrame() { this->data_size = data_size; data = new float[data_size]; - force = 0; +// force = 0; } SpectrogramFrame::~SpectrogramFrame() @@ -139,8 +139,7 @@ void SpectrogramMode::create_objects() int SpectrogramMode::handle_event() { - if(plugin->config.mode != text_to_mode(get_text())) - { + if( plugin->config.mode != text_to_mode(get_text()) ) { SpectrogramWindow *window = (SpectrogramWindow*)plugin->thread->window; window->probe_x = -1; window->probe_y = -1; @@ -153,7 +152,7 @@ int SpectrogramMode::handle_event() const char* SpectrogramMode::mode_to_text(int mode) { - switch(mode) + switch( mode ) { case VERTICAL: return _("Vertical"); @@ -165,7 +164,7 @@ const char* SpectrogramMode::mode_to_text(int mode) int SpectrogramMode::text_to_mode(const char *text) { - if(!strcmp(mode_to_text(VERTICAL), text)) return VERTICAL; + if( !strcmp(mode_to_text(VERTICAL), text) ) return VERTICAL; return HORIZONTAL; } @@ -217,7 +216,7 @@ SpectrogramWindowSizeTumbler::SpectrogramWindowSizeTumbler(Spectrogram *plugin, int SpectrogramWindowSizeTumbler::handle_up_event() { plugin->config.window_size *= 2; - if(plugin->config.window_size > MAX_WINDOW) + if( plugin->config.window_size > MAX_WINDOW ) plugin->config.window_size = MAX_WINDOW; char string[BCTEXTLEN]; sprintf(string, "%d", plugin->config.window_size); @@ -229,7 +228,7 @@ int SpectrogramWindowSizeTumbler::handle_up_event() int SpectrogramWindowSizeTumbler::handle_down_event() { plugin->config.window_size /= 2; - if(plugin->config.window_size < MIN_WINDOW) + if( plugin->config.window_size < MIN_WINDOW ) plugin->config.window_size = MIN_WINDOW; char string[BCTEXTLEN]; sprintf(string, "%d", plugin->config.window_size); @@ -301,8 +300,7 @@ SpectrogramCanvas::SpectrogramCanvas(Spectrogram *plugin, int x, int y, int w, i int SpectrogramCanvas::button_press_event() { - if(is_event_win() && cursor_inside()) - { + if( is_event_win() && cursor_inside() ) { calculate_point(); current_operation = DRAG; plugin->send_configure_change(); @@ -313,8 +311,7 @@ int SpectrogramCanvas::button_press_event() int SpectrogramCanvas::button_release_event() { - if(current_operation == DRAG) - { + if( current_operation == DRAG ) { current_operation = NONE; return 1; } @@ -323,8 +320,7 @@ int SpectrogramCanvas::button_release_event() int SpectrogramCanvas::cursor_motion_event() { - if(current_operation == DRAG) - { + if( current_operation == DRAG ) { calculate_point(); } return 0; @@ -349,11 +345,10 @@ void SpectrogramCanvas::calculate_point() void SpectrogramCanvas::draw_overlay() { SpectrogramWindow *window = (SpectrogramWindow*)plugin->thread->window; - if(window->probe_x >= 0 || window->probe_y >= 0) - { + if( window->probe_x >= 0 || window->probe_y >= 0 ) { set_color(GREEN); set_inverse(); - if(plugin->config.mode == HORIZONTAL) draw_line(0, window->probe_y, get_w(), window->probe_y); + if( plugin->config.mode == HORIZONTAL ) draw_line(0, window->probe_y, get_w(), window->probe_y); draw_line(window->probe_x, 0, window->probe_x, get_h()); set_opaque(); } @@ -418,8 +413,7 @@ void SpectrogramWindow::create_objects() x += window_size->get_w(); add_subwindow(window_size_tumbler = new SpectrogramWindowSizeTumbler(plugin, x, y)); - for(int i = MIN_WINDOW; i <= MAX_WINDOW; i *= 2) - { + for( int i = MIN_WINDOW; i <= MAX_WINDOW; i *= 2 ) { sprintf(string, "%d", i); window_size->add_item(new BC_MenuItem(string)); } @@ -486,7 +480,7 @@ int SpectrogramWindow::resize_event(int w, int h) int y_diff = -canvas_h + canvas->get_h(); // Remove all columns which may be a different size. - plugin->frame_buffer.remove_all_objects(); +// plugin->frame_buffer.remove_all_objects(); plugin->frame_history.remove_all_objects(); level_title->reposition_window( @@ -539,10 +533,10 @@ int SpectrogramWindow::resize_event(int w, int h) void SpectrogramWindow::calculate_frequency(int x, int y, int do_overlay) { - if(x < 0 && y < 0) return; + if( x < 0 && y < 0 ) return; // Clear previous overlay - if(do_overlay) canvas->draw_overlay(); + if( do_overlay ) canvas->draw_overlay(); // New probe position probe_x = x; @@ -550,32 +544,27 @@ void SpectrogramWindow::calculate_frequency(int x, int y, int do_overlay) // Convert to coordinates in frame history int freq_pixel, time_pixel; - if(plugin->config.mode == VERTICAL) - { + if( plugin->config.mode == VERTICAL ) { freq_pixel = get_w() - x; time_pixel = 0; } - else - { + else { freq_pixel = y; time_pixel = get_w() - x; } CLAMP(time_pixel, 0, plugin->frame_history.size() - 1); - if(plugin->frame_history.size()) - { + if( plugin->frame_history.size() ) { SpectrogramFrame *ptr = plugin->frame_history.get( plugin->frame_history.size() - time_pixel - 1); int pixels; int freq_index; - if(plugin->config.mode == VERTICAL) - { + if( plugin->config.mode == VERTICAL ) { pixels = canvas->get_w(); freq_index = (pixels - freq_pixel) * TOTALFREQS / pixels; } - else - { + else { pixels = canvas->get_h(); freq_index = (pixels - freq_pixel) * TOTALFREQS / pixels; } @@ -594,8 +583,7 @@ void SpectrogramWindow::calculate_frequency(int x, int y, int do_overlay) amplitude_title->update(string); } - if(do_overlay) - { + if( do_overlay ) { canvas->draw_overlay(); canvas->flash(); } @@ -647,7 +635,6 @@ Spectrogram::Spectrogram(PluginServer *server) : PluginAClient(server) { reset(); - timer = new Timer; w = xS(640); h = yS(480); } @@ -655,12 +642,9 @@ Spectrogram::Spectrogram(PluginServer *server) Spectrogram::~Spectrogram() { delete fft; - delete [] data; delete audio_buffer; delete [] freq_real; delete [] freq_imag; - delete timer; - frame_buffer.remove_all_objects(); frame_history.remove_all_objects(); } @@ -670,14 +654,11 @@ void Spectrogram::reset() thread = 0; fft = 0; done = 0; - data = 0; audio_buffer = 0; audio_buffer_start = -MAX_WINDOW * 2; freq_real = 0; freq_imag = 0; allocated_data = 0; - total_windows = 0; - bzero(&header, sizeof(data_header_t)); } @@ -689,54 +670,34 @@ int Spectrogram::process_buffer(int64_t size, int64_t start_position, int sample_rate) { -// Pass through - read_samples(buffer, - 0, - sample_rate, - start_position, - size); + int dir = get_direction() == PLAY_REVERSE ? -1 : 1; + double start_pos = (double)start_position / sample_rate; +// Pass through + read_samples(buffer, 0, sample_rate, start_position, size); load_configuration(); - // Reset audio buffer - if(window_size != config.window_size) - { + if( window_size != config.window_size ) { render_stop(); window_size = config.window_size; } - - - - - if(!fft) - { + if( !fft ) fft = new FFT; - } - - if(!data) - { - data = new unsigned char[sizeof(data_header_t)]; - allocated_data = 0; - } - if(!freq_real) - { + if( !freq_real ) { freq_real = new double[MAX_WINDOW]; freq_imag = new double[MAX_WINDOW]; } - if(!audio_buffer) - { + if( !audio_buffer ) audio_buffer = new Samples(MAX_WINDOW); - } -// Accumulate audio +// Allocate more audio buffer int needed = buffer_size + size; - if(audio_buffer->get_allocated() < needed) - { + if( audio_buffer->get_allocated() < needed ) { Samples *new_samples = new Samples(needed); memcpy(new_samples->get_data(), audio_buffer->get_data(), @@ -747,80 +708,49 @@ int Spectrogram::process_buffer(int64_t size, double *audio_samples = audio_buffer->get_data(); memcpy(audio_samples + buffer_size, - buffer->get_data(), - sizeof(double) * size); + buffer->get_data(), sizeof(double) * size); buffer_size += size; - -//printf("Spectrogram::process_buffer %d %d\n", __LINE__, buffer_size); - // Append a windows to end of GUI buffer - total_windows = 0; - while(buffer_size >= window_size) - { + while(buffer_size >= window_size) { // Process FFT fft->do_fft(window_size, // must be a power of 2 - 0, // 0 = forward FFT, 1 = inverse - audio_samples, // array of input's real samples - 0, // array of input's imag samples - freq_real, // array of output's reals - freq_imag); + 0, // 0 = forward FFT, 1 = inverse + audio_samples, // array of input's real samples + 0, // array of input's imag samples + freq_real, // array of output's reals + freq_imag); // Get peak in waveform double max = 0; - for(int i = 0; i < window_size; i++) - { + for( int i = 0; i < window_size; i++ ) { double sample = fabs(audio_samples[i]); - if(sample > max) max = sample; + if( sample > max ) max = sample; } -// Append to end of data buffer - if(allocated_data < (total_windows + 1) * (HALF_WINDOW + 1)) - { - int new_allocation = (total_windows + 1) * (HALF_WINDOW + 1); - unsigned char *new_data = new unsigned char[sizeof(data_header_t) + - sizeof(float) * new_allocation]; - data_header_t *new_header = (data_header_t*)new_data; - data_header_t *old_header = (data_header_t*)data; - memcpy(new_header->samples, - old_header->samples, - sizeof(float) * allocated_data); - delete [] data; - data = new_data; - allocated_data = new_allocation; - } - data_header_t *header = (data_header_t*)data; - float *sample_output = header->samples + total_windows * (HALF_WINDOW + 1); -// 1st sample is maximum - sample_output[0] = max; - for(int i = 0; i < HALF_WINDOW; i++) - { - sample_output[i + 1] = sqrt(freq_real[i] * freq_real[i] + - freq_imag[i] * freq_imag[i]); -// sample_output[i + 1] = freq_real[i]; +// send to the GUI + SpectrogramFrame *frame = new SpectrogramFrame(HALF_WINDOW + 1); + double widx = get_gui_frames(); + frame->position = start_pos + dir * window_size * widx / get_samplerate(); + frame->data[0] = max; + for( int i = 0; i < HALF_WINDOW; i++ ) { + frame->data[i + 1] = hypot(freq_real[i], freq_imag[i]); } + frame->window_size = window_size; + frame->sample_rate = sample_rate; + frame->level = DB::fromdb(config.level); + add_gui_frame(frame); // Shift audio buffer out memcpy(audio_samples, audio_samples + window_size, (buffer_size - window_size) * sizeof(double)); - total_windows++; buffer_size -= window_size; } - data_header_t *header = (data_header_t*)data; - header->window_size = window_size; - header->sample_rate = sample_rate; - header->total_windows = total_windows; -// Linear output level - header->level = DB::fromdb(config.level); - - send_render_gui(data, - sizeof(data_header_t) + - sizeof(float) * total_windows * (HALF_WINDOW + 1)); - + last_position = start_position + dir * size; return 0; } @@ -828,389 +758,277 @@ void Spectrogram::render_stop() { buffer_size = 0; audio_buffer_start = -MAX_WINDOW * 2; - frame_buffer.remove_all_objects(); +// frame_buffer.remove_all_objects(); frame_history.remove_all_objects(); } - - - NEW_WINDOW_MACRO(Spectrogram, SpectrogramWindow) void Spectrogram::update_gui() { - if(thread) - { - int result = load_configuration(); - SpectrogramWindow *window = (SpectrogramWindow*)thread->get_window(); - window->lock_window("Spectrogram::update_gui"); - if(result) window->update_gui(); - - -//printf("Spectrogram::update_gui %d\n", __LINE__); -// Shift in accumulated canvas columns - if(frame_buffer.size()) - { - SpectrogramCanvas *canvas = (SpectrogramCanvas*)window->canvas; - canvas->draw_overlay(); -// Z to draw in this iteration - int total_frames = timer->get_difference() * - header.sample_rate / - header.window_size / - 1000; - -//printf("Spectrogram::update_gui %d %d %ld\n", __LINE__, frame_buffer.size(), timer->get_difference()); - if(total_frames) timer->subtract(total_frames * - header.window_size * - 1000 / - header.sample_rate); - -// Add forced column drawing - for(int i = 0; i < frame_buffer.size(); i++) - if(frame_buffer.get(i)->force) total_frames++; - total_frames = MIN(frame_buffer.size(), total_frames); - -// Limit to canvas width - if(config.mode == HORIZONTAL) - total_frames = MIN(canvas->get_w(), total_frames); - - - - if(config.mode == HORIZONTAL) - { + if( !thread ) return; + SpectrogramWindow *window = (SpectrogramWindow*)thread->get_window(); + if( !window ) return; + int result = load_configuration(); + int total_frames = pending_gui_frames(); + if( !result && !total_frames ) return; + + window->lock_window("Spectrogram::update_gui"); + if( result ) // widgets + window->update_gui(); + if( total_frames ) { // spectrogram + SpectrogramCanvas *canvas = (SpectrogramCanvas*)window->canvas; + canvas->draw_overlay(); + + if( config.mode == HORIZONTAL ) { // Shift left - int pixels = canvas->get_h(); - canvas->copy_area(total_frames * config.xzoom, - 0, - 0, - 0, - canvas->get_w() - total_frames * config.xzoom, - canvas->get_h()); + int pixels = canvas->get_h(); + canvas->copy_area(total_frames * config.xzoom, + 0, 0, 0, + canvas->get_w() - total_frames * config.xzoom, + canvas->get_h()); // Draw new columns - for(int frame = 0; - frame < total_frames; - frame++) - { - int x = canvas->get_w() - (total_frames - frame) * config.xzoom; - SpectrogramFrame *ptr = frame_buffer.get(0); - - for(int i = 0; i < pixels; i++) - { - float db = ptr->data[ - MIN(i, ptr->data_size - 1)]; - float h, s, v; - float r_out, g_out, b_out; - int r, g, b; - + for( int frame = 0; frame < total_frames; frame++ ) { + int x = canvas->get_w() - (total_frames - frame) * config.xzoom; + SpectrogramFrame *ptr = (SpectrogramFrame*)get_gui_frame(-1, 0); + fix_gui_frame(ptr); + + for( int i = 0; i < pixels; i++ ) { + float db = ptr->data[MIN(i, ptr->data_size - 1)]; + float h, s, v; + float r_out, g_out, b_out; + int r, g, b; #define DIVISION1 0.0 #define DIVISION2 -20.0 #define DIVISION3 INFINITYGAIN - if(db > DIVISION2) - { - h = 240 - (float)(db - DIVISION2) / (DIVISION1 - DIVISION2) * - 240; - CLAMP(h, 0, 240); - s = 1.0; - v = 1.0; - HSV::hsv_to_rgb(r_out, g_out, b_out, h, s, v); - r = (int)(r_out * 0xff); - g = (int)(g_out * 0xff); - b = (int)(b_out * 0xff); - } - else - if(db > DIVISION3) - { - h = 0.0; - s = 0.0; - v = (float)(db - DIVISION3) / (DIVISION2 - DIVISION3); - HSV::hsv_to_rgb(r_out, g_out, b_out, h, s, v); - r = (int)(r_out * 0xff); - g = (int)(g_out * 0xff); - b = (int)(b_out * 0xff); - } - else - { - r = g = b = 0; - } - - canvas->set_color((r << 16) | - (g << 8) | - (b)); - if(config.xzoom == 1) - canvas->draw_pixel(x, i); - else - canvas->draw_line(x, - i, - x + config.xzoom, - i); + if( db > DIVISION2 ) { + h = 240 - (float)(db - DIVISION2) / (DIVISION1 - DIVISION2) * + 240; + CLAMP(h, 0, 240); + s = 1.0; + v = 1.0; + HSV::hsv_to_rgb(r_out, g_out, b_out, h, s, v); + r = (int)(r_out * 0xff); + g = (int)(g_out * 0xff); + b = (int)(b_out * 0xff); } - -// Push frames onto history - for(int i = 0; i < config.xzoom; i++) - { - SpectrogramFrame *new_frame = new SpectrogramFrame( - ptr->data_size); - frame_history.append(new_frame); - memcpy(new_frame->data, ptr->data, sizeof(float) * ptr->data_size); + else if( db > DIVISION3 ) { + h = 0.0; + s = 0.0; + v = (float)(db - DIVISION3) / (DIVISION2 - DIVISION3); + HSV::hsv_to_rgb(r_out, g_out, b_out, h, s, v); + r = (int)(r_out * 0xff); + g = (int)(g_out * 0xff); + b = (int)(b_out * 0xff); + } + else { + r = g = b = 0; } -// Clip history to canvas size - while(frame_history.size() > canvas->get_w()) - frame_history.remove_object_number(0); + canvas->set_color((r << 16) | (g << 8) | (b)); + if( config.xzoom == 1 ) + canvas->draw_pixel(x, i); + else + canvas->draw_line(x, i, x + config.xzoom, i); + } - frame_buffer.remove_object_number(0); +// Copy a frame into history for each pixel + for( int i = 0; i < config.xzoom; i++ ) { + SpectrogramFrame *new_frame = new SpectrogramFrame( + ptr->data_size); + frame_history.append(new_frame); + memcpy(new_frame->data, ptr->data, + sizeof(float) * ptr->data_size); } +// Clip history to canvas size + while(frame_history.size() > canvas->get_w()) + frame_history.remove_object_number(0); + + delete ptr; } - else + } + else { // mode == VERTICAL - { -// Shift frames into history - for(int frame = 0; frame < total_frames; frame++) - { - if(frame_history.size() >= config.history_size) - frame_history.remove_object_number(0); - - frame_history.append(frame_buffer.get(0)); - frame_buffer.remove_number(0); - } - +// Shift frames into history buffer + for( int frame = 0; frame < total_frames; frame++ ) { + SpectrogramFrame *ptr = (SpectrogramFrame*)get_gui_frame(-1, 0); + fix_gui_frame(ptr); + frame_history.append(ptr); + } // Reduce history size - while(frame_history.size() > config.history_size) - frame_history.remove_object_number(0); + while(frame_history.size() > config.history_size) + frame_history.remove_object_number(0); // Draw frames from history - canvas->clear_box(0, 0, canvas->get_w(), canvas->get_h()); - for(int frame = 0; frame < frame_history.size(); frame++) - { - SpectrogramFrame *ptr = frame_history.get(frame); + canvas->clear_box(0, 0, canvas->get_w(), canvas->get_h()); + for( int frame = 0; frame < frame_history.size(); frame++ ) { + SpectrogramFrame *ptr = frame_history.get(frame); //printf("%d %d\n", canvas->get_w(), ptr->data_size); - int luma = (frame + 1) * 0x80 / frame_history.size(); - if(frame == frame_history.size() - 1) - { - canvas->set_color(WHITE); - canvas->set_line_width(2); - } - else - canvas->set_color((luma << 16) | - (luma << 8) | - luma); - - - int x1 = 0; - int y1 = 0; - int w = canvas->get_w(); - int h = canvas->get_h(); - int number = 0; + int luma = (frame + 1) * 0x80 / frame_history.size(); + if( frame == frame_history.size() - 1 ) { + canvas->set_color(WHITE); + canvas->set_line_width(2); + } + else + canvas->set_color((luma << 16) | (luma << 8) | luma); + int x1 = 0, y1 = 0; + int w = canvas->get_w(); + int h = canvas->get_h(); + int number = 0; //printf("Spectrogram::update_gui %d ", __LINE__); - for(int x2 = 0; x2 < w; x2++) - { - float db = ptr->data[ - MIN((w - x2), ptr->data_size - 1)]; -//if(x2 > w - 10) printf("%.02f ", ptr->data[x2]); - int y2 = h-1 - (int)((db - INFINITYGAIN) / - (0 - INFINITYGAIN) * - h); - CLAMP(y2, 0, h-1); - - if(number) - { - canvas->draw_line(x1, y1, x2, y2); - } - else - { - number++; - } - - x1 = x2; - y1 = y2; + for( int x2 = 0; x2 < w; x2++ ) { + float db = ptr->data[ + MIN((w - x2), ptr->data_size - 1)]; +//if( x2 > w - 10 ) printf("%.02f ", ptr->data[x2]); + int y2 = h - 1 - (int)((db - INFINITYGAIN) / + (0 - INFINITYGAIN) * + h); + CLAMP(y2, 0, h - 1); + + if( number ) { + canvas->draw_line(x1, y1, x2, y2); } - - canvas->set_line_width(1); -//printf("\n"); + else { + number++; + } + x1 = x2; + y1 = y2; } + canvas->set_line_width(1); +//printf("\n"); } - -// Recompute probe level - window->calculate_frequency(window->probe_x, window->probe_y, 0); - - canvas->draw_overlay(); - canvas->flash(); } +// Recompute probe level + window->calculate_frequency(window->probe_x, window->probe_y, 0); - while(frame_buffer.size() > MAX_COLUMNS) - frame_buffer.remove_object_number(0); - - window->unlock_window(); + canvas->draw_overlay(); + canvas->flash(); } + + window->unlock_window(); } -void Spectrogram::render_gui(void *data, int size) + +// convert GUI frame to canvas dimensions & normalized DB +void Spectrogram::fix_gui_frame(SpectrogramFrame *frame) { - if(thread) - { - thread->get_window()->lock_window("Spectrogram::render_gui"); - data_header_t *header = (data_header_t*)data; - memcpy(&this->header, header, sizeof(data_header_t)); - BC_SubWindow *canvas = ((SpectrogramWindow*)thread->get_window())->canvas; - int pixels = canvas->get_w(); - if(config.mode == HORIZONTAL) pixels = canvas->get_h(); - -// Set all previous columns to draw immediately - for(int i = 0; i < frame_buffer.size(); i++) - frame_buffer.get(i)->force = 1; - - - for(int current_window = 0; - current_window < header->total_windows; - current_window++) - { - float *frame = header->samples + - current_window * (header->window_size / 2 + 1); - float frame_max = *frame; - frame++; - int niquist = get_project_samplerate() / 2; - int total_slots = header->window_size / 2; - int max_slot = total_slots - 1; -// int slot1 = total_slots - 1; - SpectrogramFrame *ptr = - new SpectrogramFrame( - pixels); + int niquist = get_project_samplerate() / 2; + int total_slots = frame->window_size / 2; + int max_slot = total_slots - 1; + BC_SubWindow *canvas = ((SpectrogramWindow*)thread->get_window())->canvas; + int pixels = canvas->get_w(); + if( config.mode == HORIZONTAL ) pixels = canvas->get_h(); + +// allocate new frame + float *out_data = new float[pixels]; + float *in_data = frame->data; // Scale slots to pixels - for(int i = 0; i < pixels; i++) - { + for( int i = 0; i < pixels; i++ ) { // Low frequency of row - int freq_index1 = (int)((pixels - i) * TOTALFREQS / pixels); + int freq_index1 = (int)((pixels - i) * TOTALFREQS / pixels); // High frequency of row - int freq_index2 = (int)((pixels - i + 1) * TOTALFREQS / pixels); - int freq1 = Freq::tofreq(freq_index1); - int freq2 = Freq::tofreq(freq_index2); - float slot1_f = (float)freq1 * max_slot / niquist; - float slot2_f = (float)freq2 * max_slot / niquist; - int slot1 = (int)(slot1_f); - int slot2 = (int)(slot2_f); - slot1 = MIN(slot1, max_slot); - slot2 = MIN(slot2, max_slot); - double sum = 0; + int freq_index2 = (int)((pixels - i + 1) * TOTALFREQS / pixels); + int freq1 = Freq::tofreq(freq_index1); + int freq2 = Freq::tofreq(freq_index2); + float slot1_f = (float)freq1 * max_slot / niquist; + float slot2_f = (float)freq2 * max_slot / niquist; + int slot1 = (int)(slot1_f); + int slot2 = (int)(slot2_f); + slot1 = MIN(slot1, max_slot); + slot2 = MIN(slot2, max_slot); + double sum = 0; // Accumulate multiple slots in the same pixel - if(slot2 > slot1 + 1) - { - for(int j = slot1; j <= slot2; j++) - sum += frame[j]; + if( slot2 > slot1 + 1 ) { + for( int j = slot1; j <= slot2; j++ ) + sum += in_data[j]; - sum /= slot2 - slot1 + 1; - } - else + sum /= slot2 - slot1 + 1; + } + else { // Blend 2 slots to create pixel - { - float weight = slot1_f - floor(slot1_f); - int slot3 = MIN(slot1 + 1, max_slot); - sum = frame[slot1] * (1.0 - weight) + - frame[slot3] * weight; - } + float weight = slot1_f - floor(slot1_f); + int slot3 = MIN(slot1 + 1, max_slot); + sum = in_data[slot1] * (1.0 - weight) + + in_data[slot3] * weight; + } + + out_data[i] = sum; + } - ptr->data[i] = sum; -// slot1 = slot2; - } // Normalize - if(config.normalize) - { + if( config.normalize ) { // Get the maximum level in the spectrogram - float max = 0; - for(int i = 0; i < pixels; i++) - { - if(ptr->data[i] > max) max = ptr->data[i]; - } + float max = 0; + for( int i = 0; i < pixels; i++ ) { + if( out_data[i] > max ) max = out_data[i]; + } // Scale all levels - for(int i = 0; i < pixels; i++) - { - ptr->data[i] = header->level * - ptr->data[i] / - max; - } - } - else - { + for( int i = 0; i < pixels; i++ ) { + out_data[i] = frame->level * + out_data[i] / + max; + } + } + else { // Get the maximum level in the spectrogram - float max = 0; - for(int i = 0; i < pixels; i++) - { - if(ptr->data[i] > max) max = ptr->data[i]; - } + float max = 0; + for( int i = 0; i < pixels; i++ ) { + if( out_data[i] > max ) max = out_data[i]; + } // Maximum level in spectrogram is the maximum waveform level - for(int i = 0; i < pixels; i++) - { - ptr->data[i] = header->level * - frame_max * - ptr->data[i] / - max; - } - - -// for(int i = 0; i < pixels; i++) -// { -// ptr->data[i] = header->level * ptr->data[i]; -// } - } + float frame_max = in_data[0]; + for( int i = 0; i < pixels; i++ ) { + out_data[i] = frame->level * + frame_max * out_data[i] / max; + } + } // DB conversion //printf("Spectrogram::render_gui %d ", __LINE__); - for(int i = 0; i < pixels; i++) - { - ptr->data[i] = DB::todb(ptr->data[i]); -//if(i > pixels - 10) printf("%.02f ", ptr->data[i]); + for( int i = 0; i < pixels; i++ ) { + out_data[i] = DB::todb(out_data[i]); +//if( i > pixels - 10 ) printf("%.02f ", ptr->data[i]); - } -//printf("\n"); - - - frame_buffer.append(ptr); - total_windows++; - } - - timer->update(); - thread->get_window()->unlock_window(); } + + delete [] in_data; + frame->data = out_data; + frame->data_size = pixels; } + LOAD_CONFIGURATION_MACRO(Spectrogram, SpectrogramConfig) void Spectrogram::read_data(KeyFrame *keyframe) { +//printf("Spectrogram::read_data %d this=%p\n", __LINE__, this); FileXML input; input.set_shared_input(keyframe->xbuf); int result = 0; - while(!result) - { - result = input.read_tag(); - - if(!result) - { - if(input.tag.title_is("SPECTROGRAM")) - { - config.level = input.tag.get_property("LEVEL", config.level); - config.normalize = input.tag.get_property("NORMALIZE", config.normalize); - config.window_size = input.tag.get_property("WINDOW_SIZE", config.window_size); - config.xzoom = input.tag.get_property("XZOOM", config.xzoom); - config.mode = input.tag.get_property("MODE", config.mode); - config.history_size = input.tag.get_property("HISTORY_SIZE", config.history_size); - if(is_defaults()) - { - w = input.tag.get_property("W", w); - h = input.tag.get_property("H", h); - } + while( !(result = input.read_tag()) ) { + if( input.tag.title_is("SPECTROGRAM") ) { + config.level = input.tag.get_property("LEVEL", config.level); + config.normalize = input.tag.get_property("NORMALIZE", config.normalize); + config.window_size = input.tag.get_property("WINDOW_SIZE", config.window_size); + config.xzoom = input.tag.get_property("XZOOM", config.xzoom); + config.mode = input.tag.get_property("MODE", config.mode); + config.history_size = input.tag.get_property("HISTORY_SIZE", config.history_size); + if( is_defaults() ) { + w = input.tag.get_property("W", w); + h = input.tag.get_property("H", h); } } } @@ -1237,7 +1055,3 @@ void Spectrogram::save_data(KeyFrame *keyframe) output.terminate_string(); } - - - -