You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rosegarden/src/sound/PeakFileManager.cpp

328 lines
8.5 KiB

// -*- c-basic-offset: 4 -*-
/*
Rosegarden
A 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 <bownie@bownie.com>
The moral right of the authors to claim authorship of this work
has been asserted.
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.
*/
// Accepts a file handle positioned somewhere in sample data (could
// be at the start) along with the necessary meta information for
// decoding (channels, bits per sample) and turns the sample data
// into peak data and generates a BWF format peak chunk file. This
// file can exist by itself (in the case this is being generated
// by a WAV) or be accomodated inside a BWF format file.
//
//
#include <string>
#include <vector>
#include <tqobject.h>
#include "PeakFileManager.h"
#include "AudioFile.h"
#include "RealTime.h"
#include "PeakFile.h"
namespace Rosegarden
{
PeakFileManager::PeakFileManager():
m_updatePercentage(0),
m_currentPeakFile(0)
{}
PeakFileManager::~PeakFileManager()
{}
// Inserts PeakFile based on AudioFile if it doesn't already exist
bool
PeakFileManager::insertAudioFile(AudioFile *audioFile)
{
std::vector<PeakFile*>::iterator it;
for (it = m_peakFiles.begin(); it != m_peakFiles.end(); it++) {
if ((*it)->getAudioFile()->getId() == audioFile->getId())
return false;
}
/*
std::cout << "PeakFileManager::insertAudioFile - creating peak file "
<< m_peakFiles.size() + 1
<< " for \"" << audioFile->getFilename()
<< "\"" << std::endl;
*/
// Insert
m_peakFiles.push_back(new PeakFile(audioFile));
return true;
}
// Removes peak file from PeakFileManager - doesn't affect audioFile
//
bool
PeakFileManager::removeAudioFile(AudioFile *audioFile)
{
std::vector<PeakFile*>::iterator it;
for (it = m_peakFiles.begin(); it != m_peakFiles.end(); it++) {
if ((*it)->getAudioFile()->getId() == audioFile->getId()) {
if (m_currentPeakFile == *it)
m_currentPeakFile = 0;
delete *it;
m_peakFiles.erase(it);
return true;
}
}
return false;
}
// Auto-insert PeakFile into manager if it doesn't already exist
//
PeakFile*
PeakFileManager::getPeakFile(AudioFile *audioFile)
{
std::vector<PeakFile*>::iterator it;
PeakFile *ptr = 0;
while (ptr == 0) {
for (it = m_peakFiles.begin(); it != m_peakFiles.end(); it++)
if ((*it)->getAudioFile()->getId() == audioFile->getId())
ptr = *it;
// If nothing is found then insert and retry
//
if (ptr == 0) {
// Insert - if we fail we return as empty
//
if (insertAudioFile(audioFile) == false)
return 0;
}
}
return ptr;
}
// Does a given AudioFile have a valid peak file or peak chunk?
//
bool
PeakFileManager::hasValidPeaks(AudioFile *audioFile)
{
if (audioFile->getType() == WAV) {
// Check external peak file
PeakFile *peakFile = getPeakFile(audioFile);
if (peakFile == 0) {
#ifdef DEBUG_PEAKFILEMANAGER
std::cerr << "PeakFileManager::hasValidPeaks - no peak file found"
<< std::endl;
#endif
return false;
}
// If it doesn't open and parse correctly
if (peakFile->open() == false)
return false;
// or if the data is old or invalid
if (peakFile->isValid() == false)
return false;
} else if (audioFile->getType() == BWF) {
// check internal peak chunk
} else {
#ifdef DEBUG_PEAKFILEMANAGER
std::cout << "PeakFileManager::hasValidPeaks - unsupported file type"
<< std::endl;
#endif
return false;
}
return true;
}
// Generate the peak file. Checks to see if peak file exists
// already and if so if it's up to date. If it isn't then we
// regenerate.
//
void
PeakFileManager::generatePeaks(AudioFile *audioFile,
unsigned short updatePercentage)
{
#ifdef DEBUG_PEAKFILEMANAGER
std::cout << "PeakFileManager::generatePeaks - generating peaks for \""
<< audioFile->getFilename() << "\"" << std::endl;
#endif
if (audioFile->getType() == WAV) {
m_currentPeakFile = getPeakFile(audioFile);
TQObject::connect(m_currentPeakFile, TQT_SIGNAL(setProgress(int)),
this, TQT_SIGNAL(setProgress(int)));
// Just write out a peak file
//
if (m_currentPeakFile->write(updatePercentage) == false) {
std::cerr << "Can't write peak file for " << audioFile->getFilename() << " - no preview generated" << std::endl;
throw BadPeakFileException
(audioFile->getFilename(), __FILE__, __LINE__);
}
// The m_currentPeakFile might have been cancelled (see stopPreview())
//
if (m_currentPeakFile) {
// close writes out important things
m_currentPeakFile->close();
m_currentPeakFile->disconnect();
}
} else if (audioFile->getType() == BWF) {
// write the file out and incorporate the peak chunk
} else {
#ifdef DEBUG_PEAKFILEMANAGER
std::cerr << "PeakFileManager::generatePeaks - unsupported file type"
<< std::endl;
#endif
return ;
}
m_currentPeakFile = 0;
}
std::vector<float>
PeakFileManager::getPreview(AudioFile *audioFile,
const RealTime &startTime,
const RealTime &endTime,
int width,
bool showMinima)
{
std::vector<float> rV;
// If we've got no channels then the audio file hasn't
// completed (recording) - so don't generate a preview
//
if (audioFile->getChannels() == 0)
return rV;
if (audioFile->getType() == WAV) {
PeakFile *peakFile = getPeakFile(audioFile);
// just write out a peak file
try {
peakFile->open();
rV = peakFile->getPreview(startTime,
endTime,
width,
showMinima);
} catch (SoundFile::BadSoundFileException e) {
#ifdef DEBUG_PEAKFILEMANAGER
std::cout << "PeakFileManager::getPreview "
<< "\"" << e << "\"" << std::endl;
#else
;
#endif
throw BadPeakFileException(e);
}
} else if (audioFile->getType() == BWF) {
// write the file out and incorporate the peak chunk
}
#ifdef DEBUG_PEAKFILEMANAGER
else {
std::cerr << "PeakFileManager::getPreview - unsupported file type"
<< std::endl;
}
#endif
return rV;
}
void
PeakFileManager::clear()
{
std::vector<PeakFile*>::iterator it;
for (it = m_peakFiles.begin(); it != m_peakFiles.end(); it++)
delete (*it);
m_peakFiles.erase(m_peakFiles.begin(), m_peakFiles.end());
m_currentPeakFile = 0;
}
std::vector<SplitPointPair>
PeakFileManager::getSplitPoints(AudioFile *audioFile,
const RealTime &startTime,
const RealTime &endTime,
int threshold,
const RealTime &minTime)
{
PeakFile *peakFile = getPeakFile(audioFile);
if (peakFile == 0)
return std::vector<SplitPointPair>();
return peakFile->getSplitPoints(startTime,
endTime,
threshold,
minTime);
}
void
PeakFileManager::stopPreview()
{
if (m_currentPeakFile) {
// Stop processing
//
TQString fileName = TQString(m_currentPeakFile->getFilename().data());
m_currentPeakFile->setProcessingPeaks(false);
m_currentPeakFile->disconnect();
TQFile file(fileName);
bool removed = file.remove();
#ifdef DEBUG_PEAKFILEMANAGER
if (removed) {
std::cout << "PeakFileManager::stopPreview() - removed preview"
<< std::endl;
}
#endif
//delete m_currentPeakFile;
m_currentPeakFile = 0;
}
}
}
#include "PeakFileManager.moc"