int gWaveform::alloc(int datasize) { ratio = chan->wave->size / (float) datasize; if (ratio < 2) return 0; freeData(); data.size = datasize; data.sup = (int*) malloc(data.size * sizeof(int)); data.inf = (int*) malloc(data.size * sizeof(int)); int offset = h() / 2; int zero = y() + offset; // center, zero amplitude (-inf dB) for (int i=0; i<data.size; i++) { int pp; // point prev int pn; // point next /* resampling the waveform, hardcore way. Many thanks to * http://fourier.eng.hmc.edu/e161/lectures/resize/node3.html * Note: we use * p = j * (m-1 / n) * instead of * p = j * (m-1 / n-1) * in order to obtain 'datasize' cells to parse (and not datasize-1) */ pp = i * ((chan->wave->size - 1) / (float) datasize); pn = (i+1) * ((chan->wave->size - 1) / (float) datasize); if (pp % 2 != 0) pp -= 1; if (pn % 2 != 0) pn -= 1; float peaksup = 0.0f; float peakinf = 0.0f; int k = pp; while (k < pn) { if (chan->wave->data[k] > peaksup) peaksup = chan->wave->data[k]; // Left data only else if (chan->wave->data[k] <= peakinf) peakinf = chan->wave->data[k]; // Left data only k += 2; } data.sup[i] = zero - (peaksup * chan->boost * offset); data.inf[i] = zero - (peakinf * chan->boost * offset); // avoid window overflow if (data.sup[i] < y()) data.sup[i] = y(); if (data.inf[i] > y()+h()-1) data.inf[i] = y()+h()-1; } recalcPoints(); return 1; }
void gWaveform::openEditMenu() { if (selectionA == selectionB) return; menuOpen = true; Fl_Menu_Item menu[] = { {"Cut"}, {"Trim"}, {"Silence"}, {"Fade in"}, {"Fade out"}, {"Smooth edges"}, {"Set start/end here"}, {0} }; if (chan->status == STATUS_PLAY) { menu[0].deactivate(); menu[1].deactivate(); } Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50); b->box(G_BOX); b->textsize(11); b->textcolor(COLOR_TEXT_0); b->color(COLOR_BG_0); const Fl_Menu_Item *m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b); if (!m) { menuOpen = false; return; } /* straightSel() to ensure that point A is always lower than B */ straightSel(); if (strcmp(m->label(), "Silence") == 0) { wfx_silence(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB)); selectionA = 0; selectionB = 0; stretchToWindow(); redraw(); menuOpen = false; return; } if (strcmp(m->label(), "Set start/end here") == 0) { glue_setBeginEndChannel( (gdEditor *) window(), // parent chan, absolutePoint(selectionA) * 2, // stereo! absolutePoint(selectionB) * 2, // stereo! false, // no recalc (we do it here) false // don't check ); selectionA = 0; selectionB = 0; selectionA_abs = 0; selectionB_abs = 0; recalcPoints(); redraw(); menuOpen = false; return; } if (strcmp(m->label(), "Cut") == 0) { wfx_cut(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB)); /* for convenience reset start/end points */ glue_setBeginEndChannel( (gdEditor *) window(), chan, 0, chan->wave->size, false); selectionA = 0; selectionB = 0; selectionA_abs = 0; selectionB_abs = 0; setZoom(0); menuOpen = false; return; } if (strcmp(m->label(), "Trim") == 0) { wfx_trim(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB)); glue_setBeginEndChannel( (gdEditor *) window(), chan, 0, chan->wave->size, false); selectionA = 0; selectionB = 0; selectionA_abs = 0; selectionB_abs = 0; stretchToWindow(); menuOpen = false; redraw(); return; } if (!strcmp(m->label(), "Fade in") || !strcmp(m->label(), "Fade out")) { int type = !strcmp(m->label(), "Fade in") ? 0 : 1; wfx_fade(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB), type); selectionA = 0; selectionB = 0; stretchToWindow(); redraw(); menuOpen = false; return; } if (!strcmp(m->label(), "Smooth edges")) { wfx_smooth(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB)); selectionA = 0; selectionB = 0; stretchToWindow(); redraw(); menuOpen = false; return; } }
int gWaveform::alloc(int datasize) { ratio = chan->wave->size / (float) datasize; if (ratio < 2) return 0; freeData(); data.size = datasize; data.sup = (int*) malloc(data.size * sizeof(int)); data.inf = (int*) malloc(data.size * sizeof(int)); int offset = h() / 2; int zero = y() + offset; // center, zero amplitude (-inf dB) /* grid frequency: store a grid point every 'gridFreq' pixel. Must be * even, as always */ int gridFreq = 0; if (grid.level != 0) { gridFreq = chan->wave->size / grid.level; if (gridFreq % 2 != 0) gridFreq--; } for (int i=0; i<data.size; i++) { int pp; // point prev int pn; // point next /* resampling the waveform, hardcore way. Many thanks to * http://fourier.eng.hmc.edu/e161/lectures/resize/node3.html * Note: we use * p = j * (m-1 / n) * instead of * p = j * (m-1 / n-1) * in order to obtain 'datasize' cells to parse (and not datasize-1) */ pp = i * ((chan->wave->size - 1) / (float) datasize); pn = (i+1) * ((chan->wave->size - 1) / (float) datasize); if (pp % 2 != 0) pp -= 1; if (pn % 2 != 0) pn -= 1; float peaksup = 0.0f; float peakinf = 0.0f; /* scan the original data in chunks */ int k = pp; while (k < pn) { if (chan->wave->data[k] > peaksup) peaksup = chan->wave->data[k]; // FIXME - Left data only else if (chan->wave->data[k] <= peakinf) peakinf = chan->wave->data[k]; // FIXME - Left data only /* print grid */ if (gridFreq != 0) if (k % gridFreq == 0 && k != 0) grid.points.add(i); k += 2; } data.sup[i] = zero - (peaksup * chan->boost * offset); data.inf[i] = zero - (peakinf * chan->boost * offset); // avoid window overflow if (data.sup[i] < y()) data.sup[i] = y(); if (data.inf[i] > y()+h()-1) data.inf[i] = y()+h()-1; } recalcPoints(); return 1; }