|
|
|
/*
|
|
|
|
Rosegarden
|
|
|
|
A MIDI and audio sequencer and musical notation editor.
|
|
|
|
|
|
|
|
This program is Copyright 2000-2008
|
|
|
|
Guillaume Laurent <glaurent@telegraph-road.org>,
|
|
|
|
Chris Cannam <cannam@all-day-breakfast.com>,
|
|
|
|
Richard Bown <richard.bown@ferventsoftware.com>
|
|
|
|
|
|
|
|
The moral rights of Guillaume Laurent, Chris Cannam, and Richard
|
|
|
|
Bown to claim authorship of this work have been asserted.
|
|
|
|
|
|
|
|
Other copyrights also apply to some parts of this work. Please
|
|
|
|
see the AUTHORS file and individual file headers for details.
|
|
|
|
|
|
|
|
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 the Free Software Foundation; either version 2 of the
|
|
|
|
License, or (at your option) any later version. See the file
|
|
|
|
COPYING included with this distribution for more information.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "AudioSplitDialog.h"
|
|
|
|
#include <tdeapplication.h>
|
|
|
|
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include "misc/Debug.h"
|
|
|
|
#include "misc/Strings.h"
|
|
|
|
#include "base/Exception.h"
|
|
|
|
#include "base/RealTime.h"
|
|
|
|
#include "base/Segment.h"
|
|
|
|
#include "document/RosegardenGUIDoc.h"
|
|
|
|
#include "gui/application/RosegardenApplication.h"
|
|
|
|
#include "sound/AudioFileManager.h"
|
|
|
|
#include <kdialogbase.h>
|
|
|
|
#include <tqcanvas.h>
|
|
|
|
#include <tqhbox.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqpalette.h>
|
|
|
|
#include <tqscrollview.h>
|
|
|
|
#include <tqspinbox.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
#include <tqvbox.h>
|
|
|
|
#include <tqwidget.h>
|
|
|
|
|
|
|
|
|
|
|
|
namespace Rosegarden
|
|
|
|
{
|
|
|
|
|
|
|
|
AudioSplitDialog::AudioSplitDialog(TQWidget *parent,
|
|
|
|
Segment *segment,
|
|
|
|
RosegardenGUIDoc *doc):
|
|
|
|
KDialogBase(parent, 0, true,
|
|
|
|
i18n("Autosplit Audio Segment"), Ok | Cancel),
|
|
|
|
m_doc(doc),
|
|
|
|
m_segment(segment),
|
|
|
|
m_canvasWidth(500),
|
|
|
|
m_canvasHeight(200),
|
|
|
|
m_previewWidth(400),
|
|
|
|
m_previewHeight(100)
|
|
|
|
{
|
|
|
|
if (!segment || segment->getType() != Segment::Audio)
|
|
|
|
reject();
|
|
|
|
|
|
|
|
TQVBox *w = makeVBoxMainWidget();
|
|
|
|
|
|
|
|
new TQLabel(i18n("AutoSplit Segment \"") +
|
|
|
|
strtoqstr(m_segment->getLabel()) + TQString("\""), w);
|
|
|
|
|
|
|
|
m_canvas = new TQCanvas(w);
|
|
|
|
m_canvas->resize(m_canvasWidth, m_canvasHeight);
|
|
|
|
m_canvasView = new TQCanvasView(m_canvas, w);
|
|
|
|
m_canvasView->setFixedWidth(m_canvasWidth);
|
|
|
|
m_canvasView->setFixedHeight(m_canvasHeight);
|
|
|
|
|
|
|
|
m_canvasView->setHScrollBarMode(TQScrollView::AlwaysOff);
|
|
|
|
m_canvasView->setVScrollBarMode(TQScrollView::AlwaysOff);
|
|
|
|
m_canvasView->setDragAutoScroll(false);
|
|
|
|
|
|
|
|
TQHBox *hbox = new TQHBox(w);
|
|
|
|
new TQLabel(i18n("Threshold"), hbox);
|
|
|
|
m_thresholdSpin = new TQSpinBox(hbox);
|
|
|
|
m_thresholdSpin->setSuffix(" %");
|
|
|
|
connect(m_thresholdSpin, TQ_SIGNAL(valueChanged(int)),
|
|
|
|
TQ_SLOT(slotThresholdChanged(int)));
|
|
|
|
|
|
|
|
// ensure this is cleared
|
|
|
|
m_previewBoxes.clear();
|
|
|
|
|
|
|
|
// Set thresholds
|
|
|
|
//
|
|
|
|
int threshold = 1;
|
|
|
|
m_thresholdSpin->setValue(threshold);
|
|
|
|
drawPreview();
|
|
|
|
drawSplits(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AudioSplitDialog::drawPreview()
|
|
|
|
{
|
|
|
|
// Delete everything on the canvas
|
|
|
|
//
|
|
|
|
TQCanvasItemList list = m_canvas->allItems();
|
|
|
|
for (TQCanvasItemList::Iterator it = list.begin(); it != list.end(); it++)
|
|
|
|
delete *it;
|
|
|
|
|
|
|
|
// empty the preview boxes
|
|
|
|
m_previewBoxes.erase(m_previewBoxes.begin(), m_previewBoxes.end());
|
|
|
|
|
|
|
|
// Draw a bounding box
|
|
|
|
//
|
|
|
|
int border = 5;
|
|
|
|
TQCanvasRectangle *rect = new TQCanvasRectangle(m_canvas);
|
|
|
|
rect->setSize(m_canvasWidth - border * 2, m_canvasHeight - border * 2);
|
|
|
|
rect->setX(border);
|
|
|
|
rect->setY(border);
|
|
|
|
rect->setZ(1);
|
|
|
|
rect->setPen(kapp->palette().color(TQPalette::Active, TQColorGroup::Dark));
|
|
|
|
rect->setBrush(kapp->palette().color(TQPalette::Active, TQColorGroup::Base));
|
|
|
|
rect->setVisible(true);
|
|
|
|
|
|
|
|
// Get preview in vector form
|
|
|
|
//
|
|
|
|
AudioFileManager &aFM = m_doc->getAudioFileManager();
|
|
|
|
int channels = aFM.getAudioFile(m_segment->getAudioFileId())->getChannels();
|
|
|
|
|
|
|
|
std::vector<float> values;
|
|
|
|
|
|
|
|
try {
|
|
|
|
values = aFM.getPreview(m_segment->getAudioFileId(),
|
|
|
|
m_segment->getAudioStartTime(),
|
|
|
|
m_segment->getAudioEndTime(),
|
|
|
|
m_previewWidth,
|
|
|
|
false);
|
|
|
|
} catch (Exception e) {
|
|
|
|
TQCanvasText *text = new TQCanvasText(m_canvas);
|
|
|
|
text->setColor(kapp->palette().
|
|
|
|
color(TQPalette::Active, TQColorGroup::Shadow));
|
|
|
|
text->setText(i18n("<no preview generated for this audio file>"));
|
|
|
|
text->setX(30);
|
|
|
|
text->setY(30);
|
|
|
|
text->setZ(4);
|
|
|
|
text->setVisible(true);
|
|
|
|
m_canvas->update();
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
int startX = (m_canvasWidth - m_previewWidth) / 2;
|
|
|
|
int halfHeight = m_canvasHeight / 2;
|
|
|
|
float h1, h2;
|
|
|
|
std::vector<float>::iterator it = values.begin();
|
|
|
|
|
|
|
|
// Draw preview
|
|
|
|
//
|
|
|
|
for (int i = 0; i < m_previewWidth; i++) {
|
|
|
|
if (channels == 1) {
|
|
|
|
h1 = *(it++);
|
|
|
|
h2 = h1;
|
|
|
|
} else {
|
|
|
|
h1 = *(it++);
|
|
|
|
h2 = *(it++);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int startY = halfHeight + int(h1 * float(m_previewHeight / 2));
|
|
|
|
int endY = halfHeight - int(h2 * float(m_previewHeight / 2));
|
|
|
|
|
|
|
|
if ( startY < 0 ) {
|
|
|
|
RG_DEBUG << "AudioSplitDialog::AudioSplitDialog - "
|
|
|
|
<< "startY - out of negative range"
|
|
|
|
<< endl;
|
|
|
|
startY = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (endY < 0) {
|
|
|
|
RG_DEBUG << "AudioSplitDialog::AudioSplitDialog - "
|
|
|
|
<< "endY - out of negative range"
|
|
|
|
<< endl;
|
|
|
|
endY = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQCanvasLine *line = new TQCanvasLine(m_canvas);
|
|
|
|
line->setPoints(startX + i,
|
|
|
|
startY,
|
|
|
|
startX + i,
|
|
|
|
endY);
|
|
|
|
line->setZ(3);
|
|
|
|
line->setPen(kapp->
|
|
|
|
palette().color(TQPalette::Active, TQColorGroup::Shadow));
|
|
|
|
line->setBrush(kapp->
|
|
|
|
palette().color(TQPalette::Active, TQColorGroup::Shadow));
|
|
|
|
line->setVisible(true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw zero dc line
|
|
|
|
//
|
|
|
|
rect = new TQCanvasRectangle(m_canvas);
|
|
|
|
rect->setX(startX);
|
|
|
|
rect->setY(halfHeight - 1);
|
|
|
|
rect->setSize(m_previewWidth, 2);
|
|
|
|
rect->setPen(kapp->palette().color(TQPalette::Active, TQColorGroup::Shadow));
|
|
|
|
rect->setBrush(kapp->palette().color(TQPalette::Active, TQColorGroup::Shadow));
|
|
|
|
rect->setZ(4);
|
|
|
|
rect->setVisible(true);
|
|
|
|
|
|
|
|
// Start time
|
|
|
|
//
|
|
|
|
char msecs[100];
|
|
|
|
sprintf(msecs, "%03d", m_segment->getAudioStartTime().msec());
|
|
|
|
TQString startText = TQString("%1.%2s")
|
|
|
|
.arg(m_segment->getAudioStartTime().sec)
|
|
|
|
.arg(msecs);
|
|
|
|
TQCanvasText *text = new TQCanvasText(m_canvas);
|
|
|
|
text->setColor(
|
|
|
|
kapp->palette().color(TQPalette::Active, TQColorGroup::Shadow));
|
|
|
|
text->setText(startText);
|
|
|
|
text->setX(startX - 20);
|
|
|
|
text->setY(m_canvasHeight / 2 - m_previewHeight / 2 - 35);
|
|
|
|
text->setZ(3);
|
|
|
|
text->setVisible(true);
|
|
|
|
|
|
|
|
rect = new TQCanvasRectangle(m_canvas);
|
|
|
|
rect->setX(startX - 1);
|
|
|
|
rect->setY(m_canvasHeight / 2 - m_previewHeight / 2 - 14);
|
|
|
|
rect->setSize(1, m_previewHeight + 28);
|
|
|
|
rect->setPen(kapp->palette().color(TQPalette::Active, TQColorGroup::Shadow));
|
|
|
|
rect->setZ(3);
|
|
|
|
rect->setVisible(true);
|
|
|
|
|
|
|
|
// End time
|
|
|
|
//
|
|
|
|
sprintf(msecs, "%03d", m_segment->getAudioEndTime().msec());
|
|
|
|
TQString endText = TQString("%1.%2s")
|
|
|
|
.arg(m_segment->getAudioEndTime().sec)
|
|
|
|
.arg(msecs);
|
|
|
|
text = new TQCanvasText(m_canvas);
|
|
|
|
text->setColor(
|
|
|
|
kapp->palette().color(TQPalette::Active, TQColorGroup::Shadow));
|
|
|
|
text->setText(endText);
|
|
|
|
text->setX(startX + m_previewWidth - 20);
|
|
|
|
text->setY(m_canvasHeight / 2 - m_previewHeight / 2 - 35);
|
|
|
|
text->setZ(3);
|
|
|
|
text->setVisible(true);
|
|
|
|
|
|
|
|
rect = new TQCanvasRectangle(m_canvas);
|
|
|
|
rect->setX(startX + m_previewWidth - 1);
|
|
|
|
rect->setY(m_canvasHeight / 2 - m_previewHeight / 2 - 14);
|
|
|
|
rect->setSize(1, m_previewHeight + 28);
|
|
|
|
rect->setPen(kapp->palette().color(TQPalette::Active, TQColorGroup::Shadow));
|
|
|
|
rect->setZ(3);
|
|
|
|
rect->setVisible(true);
|
|
|
|
|
|
|
|
m_canvas->update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AudioSplitDialog::drawSplits(int threshold)
|
|
|
|
{
|
|
|
|
// Now get the current split points and paint them
|
|
|
|
//
|
|
|
|
RealTime startTime = m_segment->getAudioStartTime();
|
|
|
|
RealTime endTime = m_segment->getAudioEndTime();
|
|
|
|
|
|
|
|
AudioFileManager &aFM = m_doc->getAudioFileManager();
|
|
|
|
std::vector<SplitPointPair> splitPoints =
|
|
|
|
aFM.getSplitPoints(m_segment->getAudioFileId(),
|
|
|
|
startTime,
|
|
|
|
endTime,
|
|
|
|
threshold);
|
|
|
|
|
|
|
|
std::vector<SplitPointPair>::iterator it;
|
|
|
|
std::vector<TQCanvasRectangle*> tempRects;
|
|
|
|
|
|
|
|
RealTime length = endTime - startTime;
|
|
|
|
double ticksPerUsec = double(m_previewWidth) /
|
|
|
|
double((length.sec * 1000000.0) + length.usec());
|
|
|
|
|
|
|
|
int startX = (m_canvasWidth - m_previewWidth) / 2;
|
|
|
|
int halfHeight = m_canvasHeight / 2;
|
|
|
|
int x1, x2;
|
|
|
|
int overlapHeight = 10;
|
|
|
|
|
|
|
|
for (it = splitPoints.begin(); it != splitPoints.end(); it++) {
|
|
|
|
RealTime splitStart = it->first - startTime;
|
|
|
|
RealTime splitEnd = it->second - startTime;
|
|
|
|
|
|
|
|
x1 = int(ticksPerUsec * double(double(splitStart.sec) *
|
|
|
|
1000000.0 + (double)splitStart.usec()));
|
|
|
|
|
|
|
|
x2 = int(ticksPerUsec * double(double(splitEnd.sec) *
|
|
|
|
1000000.0 + double(splitEnd.usec())));
|
|
|
|
|
|
|
|
TQCanvasRectangle *rect = new TQCanvasRectangle(m_canvas);
|
|
|
|
rect->setX(startX + x1);
|
|
|
|
rect->setY(halfHeight - m_previewHeight / 2 - overlapHeight / 2);
|
|
|
|
rect->setZ(2);
|
|
|
|
rect->setSize(x2 - x1, m_previewHeight + overlapHeight);
|
|
|
|
rect->setPen(kapp->
|
|
|
|
palette().color(TQPalette::Active, TQColorGroup::Mid));
|
|
|
|
rect->setBrush(kapp->
|
|
|
|
palette().color(TQPalette::Active, TQColorGroup::Mid));
|
|
|
|
rect->setVisible(true);
|
|
|
|
tempRects.push_back(rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<TQCanvasRectangle*>::iterator pIt;
|
|
|
|
|
|
|
|
// We've written the new Rects, now delete the old ones
|
|
|
|
//
|
|
|
|
if (m_previewBoxes.size()) {
|
|
|
|
// clear any previous preview boxes
|
|
|
|
//
|
|
|
|
for (pIt = m_previewBoxes.begin(); pIt != m_previewBoxes.end(); pIt++) {
|
|
|
|
//(*pIt)->setVisible(false);
|
|
|
|
delete (*pIt);
|
|
|
|
}
|
|
|
|
m_previewBoxes.erase(m_previewBoxes.begin(), m_previewBoxes.end());
|
|
|
|
m_canvas->update();
|
|
|
|
}
|
|
|
|
m_canvas->update();
|
|
|
|
|
|
|
|
// Now store the new ones
|
|
|
|
//
|
|
|
|
for (pIt = tempRects.begin(); pIt != tempRects.end(); pIt++)
|
|
|
|
m_previewBoxes.push_back(*pIt);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AudioSplitDialog::slotThresholdChanged(int threshold)
|
|
|
|
{
|
|
|
|
drawSplits(threshold);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
#include "AudioSplitDialog.moc"
|