Merge pull request #51 from pljones/multiple-frame-sizes-in-recorder
Multiple frame sizes in recorder
This commit is contained in:
commit
82935c8cd1
5 changed files with 42 additions and 34 deletions
|
@ -55,7 +55,7 @@ using namespace recorder;
|
||||||
* @param trackItem the details of where the item is in the track, along with the RIFF WAVE filename
|
* @param trackItem the details of where the item is in the track, along with the RIFF WAVE filename
|
||||||
* @param iid the sequential item id
|
* @param iid the sequential item id
|
||||||
*/
|
*/
|
||||||
CReaperItem::CReaperItem(const QString& name, const STrackItem& trackItem, const qint32& iid)
|
CReaperItem::CReaperItem(const QString& name, const STrackItem& trackItem, const qint32& iid, int frameSize)
|
||||||
{
|
{
|
||||||
QString wavName = trackItem.fileName; // assume RPP in same location...
|
QString wavName = trackItem.fileName; // assume RPP in same location...
|
||||||
|
|
||||||
|
@ -64,8 +64,8 @@ CReaperItem::CReaperItem(const QString& name, const STrackItem& trackItem, const
|
||||||
sOut << " <ITEM " << endl;
|
sOut << " <ITEM " << endl;
|
||||||
sOut << " FADEIN 0 0 0 0 0 0" << endl;
|
sOut << " FADEIN 0 0 0 0 0 0" << endl;
|
||||||
sOut << " FADEOUT 0 0 0 0 0 0" << endl;
|
sOut << " FADEOUT 0 0 0 0 0 0" << endl;
|
||||||
sOut << " POSITION " << secondsAt48K(trackItem.startFrame) << endl;
|
sOut << " POSITION " << secondsAt48K( trackItem.startFrame, frameSize ) << endl;
|
||||||
sOut << " LENGTH " << secondsAt48K(trackItem.frameCount) << endl;
|
sOut << " LENGTH " << secondsAt48K( trackItem.frameCount, frameSize ) << endl;
|
||||||
sOut << " IGUID " << iguid.toString() << endl;
|
sOut << " IGUID " << iguid.toString() << endl;
|
||||||
sOut << " IID " << iid << endl;
|
sOut << " IID " << iid << endl;
|
||||||
sOut << " NAME " << name << endl;
|
sOut << " NAME " << name << endl;
|
||||||
|
@ -86,7 +86,7 @@ CReaperItem::CReaperItem(const QString& name, const STrackItem& trackItem, const
|
||||||
* @param iid the sequential track id
|
* @param iid the sequential track id
|
||||||
* @param items the list of items in the track
|
* @param items the list of items in the track
|
||||||
*/
|
*/
|
||||||
CReaperTrack::CReaperTrack(QString name, qint32& iid, QList<STrackItem> items)
|
CReaperTrack::CReaperTrack(QString name, qint32& iid, QList<STrackItem> items, int frameSize)
|
||||||
{
|
{
|
||||||
QTextStream sOut(&out);
|
QTextStream sOut(&out);
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ CReaperTrack::CReaperTrack(QString name, qint32& iid, QList<STrackItem> items)
|
||||||
|
|
||||||
int ino = 1;
|
int ino = 1;
|
||||||
foreach (auto item, items) {
|
foreach (auto item, items) {
|
||||||
sOut << CReaperItem(name + " (" + QString::number(ino) + ")", item, iid).toString() << endl;
|
sOut << CReaperItem(name + " (" + QString::number(ino) + ")", item, iid, frameSize).toString() << endl;
|
||||||
ino++;
|
ino++;
|
||||||
iid++;
|
iid++;
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ CReaperTrack::CReaperTrack(QString name, qint32& iid, QList<STrackItem> items)
|
||||||
* @brief CReaperProject::CReaperProject Construct a Reaper RPP "<REAPER_PROJECT>" for a given list of tracks
|
* @brief CReaperProject::CReaperProject Construct a Reaper RPP "<REAPER_PROJECT>" for a given list of tracks
|
||||||
* @param tracks the list of tracks
|
* @param tracks the list of tracks
|
||||||
*/
|
*/
|
||||||
CReaperProject::CReaperProject(QMap<QString, QList<STrackItem>> tracks)
|
CReaperProject::CReaperProject(QMap<QString, QList<STrackItem>> tracks, int frameSize)
|
||||||
{
|
{
|
||||||
QTextStream sOut(&out);
|
QTextStream sOut(&out);
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ CReaperProject::CReaperProject(QMap<QString, QList<STrackItem>> tracks)
|
||||||
qint32 iid = 0;
|
qint32 iid = 0;
|
||||||
foreach(auto trackName, tracks.keys())
|
foreach(auto trackName, tracks.keys())
|
||||||
{
|
{
|
||||||
sOut << CReaperTrack(trackName, iid, tracks[trackName]).toString() << endl;
|
sOut << CReaperTrack(trackName, iid, tracks[trackName], frameSize).toString() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
sOut << ">";
|
sOut << ">";
|
||||||
|
|
|
@ -52,7 +52,7 @@ class CReaperItem : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CReaperItem(const QString& name, const STrackItem& trackItem, const qint32& iid);
|
CReaperItem( const QString& name, const STrackItem& trackItem, const qint32& iid, int frameSize );
|
||||||
QString toString() { return out; }
|
QString toString() { return out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -60,7 +60,11 @@ private:
|
||||||
const QUuid guid = QUuid::createUuid();
|
const QUuid guid = QUuid::createUuid();
|
||||||
QString out;
|
QString out;
|
||||||
|
|
||||||
inline QString secondsAt48K(const qint64 frames) { return QString::number(static_cast<double>(frames * SYSTEM_FRAME_SIZE_SAMPLES) / 48000, 'f', 14); }
|
inline QString secondsAt48K( const qint64 frames,
|
||||||
|
const int frameSize )
|
||||||
|
{
|
||||||
|
return QString::number( static_cast<double>( frames * frameSize ) / 48000, 'f', 14 );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CReaperTrack : public QObject
|
class CReaperTrack : public QObject
|
||||||
|
@ -68,7 +72,7 @@ class CReaperTrack : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CReaperTrack(QString name, qint32 &iid, QList<STrackItem> items);
|
CReaperTrack( QString name, qint32 &iid, QList<STrackItem> items, int frameSize );
|
||||||
QString toString() { return out; }
|
QString toString() { return out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -81,7 +85,7 @@ class CReaperProject : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CReaperProject(QMap<QString, QList<STrackItem> > tracks);
|
CReaperProject( QMap<QString, QList<STrackItem> > tracks, int frameSize );
|
||||||
QString toString() { return out; }
|
QString toString() { return out; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -70,11 +70,11 @@ CJamClient::CJamClient(const qint64 frame, const int _numChannels, const QString
|
||||||
* @param _name The client's current name
|
* @param _name The client's current name
|
||||||
* @param pcm The PCM data
|
* @param pcm The PCM data
|
||||||
*/
|
*/
|
||||||
void CJamClient::Frame(const QString _name, const CVector<int16_t>& pcm)
|
void CJamClient::Frame(const QString _name, const CVector<int16_t>& pcm, int iServerFrameSizeSamples)
|
||||||
{
|
{
|
||||||
name = _name;
|
name = _name;
|
||||||
|
|
||||||
for(int i = 0; i < numChannels * SYSTEM_FRAME_SIZE_SAMPLES; i++)
|
for(int i = 0; i < numChannels * iServerFrameSizeSamples; i++)
|
||||||
{
|
{
|
||||||
*out << pcm[i];
|
*out << pcm[i];
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ void CJamSession::DisconnectClient(int iChID)
|
||||||
*
|
*
|
||||||
* Also manages the overall current frame counter for the session.
|
* Also manages the overall current frame counter for the session.
|
||||||
*/
|
*/
|
||||||
void CJamSession::Frame(const int iChID, const QString name, const CHostAddress address, const int numAudioChannels, const CVector<int16_t> data)
|
void CJamSession::Frame(const int iChID, const QString name, const CHostAddress address, const int numAudioChannels, const CVector<int16_t> data, int iServerFrameSizeSamples)
|
||||||
{
|
{
|
||||||
if (vecptrJamClients[iChID] == nullptr)
|
if (vecptrJamClients[iChID] == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -193,7 +193,7 @@ void CJamSession::Frame(const int iChID, const QString name, const CHostAddress
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vecptrJamClients[iChID]->Frame(name, data);
|
vecptrJamClients[iChID]->Frame(name, data, iServerFrameSizeSamples);
|
||||||
|
|
||||||
// If _any_ connected client frame steps past currentFrame, increase currentFrame
|
// If _any_ connected client frame steps past currentFrame, increase currentFrame
|
||||||
if (vecptrJamClients[iChID]->StartFrame() + vecptrJamClients[iChID]->FrameCount() > currentFrame)
|
if (vecptrJamClients[iChID]->StartFrame() + vecptrJamClients[iChID]->FrameCount() > currentFrame)
|
||||||
|
@ -250,7 +250,7 @@ QMap<QString, QList<STrackItem>> CJamSession::Tracks()
|
||||||
* @param sessionDirName the directory name to scan
|
* @param sessionDirName the directory name to scan
|
||||||
* @return a map of (latest) client name to connection items
|
* @return a map of (latest) client name to connection items
|
||||||
*/
|
*/
|
||||||
QMap<QString, QList<STrackItem>> CJamSession::TracksFromSessionDir(const QString& sessionDirName)
|
QMap<QString, QList<STrackItem>> CJamSession::TracksFromSessionDir(const QString& sessionDirName, int iServerFrameSizeSamples)
|
||||||
{
|
{
|
||||||
QMap<QString, QList<STrackItem>> tracks;
|
QMap<QString, QList<STrackItem>> tracks;
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ QMap<QString, QList<STrackItem>> CJamSession::TracksFromSessionDir(const QString
|
||||||
}
|
}
|
||||||
|
|
||||||
QFileInfo fiEntry(sessionDir.absoluteFilePath(entry));
|
QFileInfo fiEntry(sessionDir.absoluteFilePath(entry));
|
||||||
qint64 length = fiEntry.size() / numChannels.toInt() / SYSTEM_FRAME_SIZE_SAMPLES;
|
qint64 length = fiEntry.size() / numChannels.toInt() / iServerFrameSizeSamples;
|
||||||
|
|
||||||
STrackItem track (
|
STrackItem track (
|
||||||
numChannels.toInt(),
|
numChannels.toInt(),
|
||||||
|
@ -295,7 +295,8 @@ QMap<QString, QList<STrackItem>> CJamSession::TracksFromSessionDir(const QString
|
||||||
* @brief CJamRecorder::Init Create recording directory, if necessary, and connect signal handlers
|
* @brief CJamRecorder::Init Create recording directory, if necessary, and connect signal handlers
|
||||||
* @param server Server object emiting signals
|
* @param server Server object emiting signals
|
||||||
*/
|
*/
|
||||||
void CJamRecorder::Init(const CServer* server)
|
void CJamRecorder::Init( const CServer* server,
|
||||||
|
const int _iServerFrameSizeSamples )
|
||||||
{
|
{
|
||||||
QFileInfo fi(recordBaseDir.absolutePath());
|
QFileInfo fi(recordBaseDir.absolutePath());
|
||||||
fi.setCaching(false);
|
fi.setCaching(false);
|
||||||
|
@ -325,6 +326,8 @@ void CJamRecorder::Init(const CServer* server)
|
||||||
QObject::connect((const QObject *)server, SIGNAL ( AudioFrame(const int, const QString, const CHostAddress, const int, const CVector<int16_t>) ),
|
QObject::connect((const QObject *)server, SIGNAL ( AudioFrame(const int, const QString, const CHostAddress, const int, const CVector<int16_t>) ),
|
||||||
this, SLOT( OnFrame(const int, const QString, const CHostAddress, const int, const CVector<int16_t>) ),
|
this, SLOT( OnFrame(const int, const QString, const CHostAddress, const int, const CVector<int16_t>) ),
|
||||||
Qt::ConnectionType::QueuedConnection);
|
Qt::ConnectionType::QueuedConnection);
|
||||||
|
|
||||||
|
iServerFrameSizeSamples = _iServerFrameSizeSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -353,15 +356,15 @@ void CJamRecorder::OnEnd()
|
||||||
|
|
||||||
if (fi.exists())
|
if (fi.exists())
|
||||||
{
|
{
|
||||||
tsConsole << "CJamRecorder::OnEnd() - " << fi.absolutePath() << " exists and will not be overwritten." << endl;
|
qWarning() << "CJamRecorder::OnEnd():" << fi.absolutePath() << "exists and will not be overwritten.";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QFile outf (reaperProjectFileName);
|
QFile outf (reaperProjectFileName);
|
||||||
outf.open(QFile::WriteOnly);
|
outf.open(QFile::WriteOnly);
|
||||||
QTextStream out(&outf);
|
QTextStream out(&outf);
|
||||||
out << CReaperProject(currentSession->Tracks()).toString() << endl;
|
out << CReaperProject( currentSession->Tracks(), iServerFrameSizeSamples ).toString() << endl;
|
||||||
tsConsole << "Session RPP: " << reaperProjectFileName << endl;
|
qDebug() << "Session RPP:" << reaperProjectFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete currentSession;
|
delete currentSession;
|
||||||
|
@ -373,7 +376,7 @@ void CJamRecorder::OnEnd()
|
||||||
* @brief CJamRecorder::SessionDirToReaper Replica of CJamRecorder::OnEnd() but using the directory contents to construct the CReaperProject object
|
* @brief CJamRecorder::SessionDirToReaper Replica of CJamRecorder::OnEnd() but using the directory contents to construct the CReaperProject object
|
||||||
* @param strSessionDirName
|
* @param strSessionDirName
|
||||||
*/
|
*/
|
||||||
void CJamRecorder::SessionDirToReaper(QString& strSessionDirName)
|
void CJamRecorder::SessionDirToReaper(QString& strSessionDirName, int serverFrameSizeSamples)
|
||||||
{
|
{
|
||||||
const QFileInfo fiSessionDir(QDir::cleanPath(strSessionDirName));
|
const QFileInfo fiSessionDir(QDir::cleanPath(strSessionDirName));
|
||||||
if (!fiSessionDir.exists() || !fiSessionDir.isDir())
|
if (!fiSessionDir.exists() || !fiSessionDir.isDir())
|
||||||
|
@ -395,9 +398,9 @@ void CJamRecorder::SessionDirToReaper(QString& strSessionDirName)
|
||||||
}
|
}
|
||||||
QTextStream out(&outf);
|
QTextStream out(&outf);
|
||||||
|
|
||||||
out << CReaperProject(CJamSession::TracksFromSessionDir(fiSessionDir.absoluteFilePath())).toString() << endl;
|
out << CReaperProject( CJamSession::TracksFromSessionDir( fiSessionDir.absoluteFilePath(), serverFrameSizeSamples ), serverFrameSizeSamples ).toString() << endl;
|
||||||
|
|
||||||
(*(new ConsoleWriterFactory())->get()) << "Session RPP: " << reaperProjectFileName << endl;
|
qDebug() << "Session RPP:" << reaperProjectFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -408,11 +411,11 @@ void CJamRecorder::OnDisconnected(int iChID)
|
||||||
{
|
{
|
||||||
if (!isRecording)
|
if (!isRecording)
|
||||||
{
|
{
|
||||||
tsConsole << "CJamRecorder::OnDisconnected: channel " << iChID << " disconnected but not recording" << endl;
|
qWarning() << "CJamRecorder::OnDisconnected: channel" << iChID << "disconnected but not recording";
|
||||||
}
|
}
|
||||||
if (currentSession == nullptr)
|
if (currentSession == nullptr)
|
||||||
{
|
{
|
||||||
tsConsole << "CJamRecorder::OnDisconnected: channel " << iChID << " disconnected but no currentSession" << endl;
|
qWarning() << "CJamRecorder::OnDisconnected: channel" << iChID << "disconnected but no currentSession";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentSession->DisconnectClient(iChID);
|
currentSession->DisconnectClient(iChID);
|
||||||
|
@ -436,5 +439,5 @@ void CJamRecorder::OnFrame(const int iChID, const QString name, const CHostAddre
|
||||||
OnStart();
|
OnStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSession->Frame(iChID, name, address, numAudioChannels, data);
|
currentSession->Frame( iChID, name, address, numAudioChannels, data, iServerFrameSizeSamples );
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ class CJamClient : public QObject
|
||||||
public:
|
public:
|
||||||
CJamClient(const qint64 frame, const int numChannels, const QString name, const CHostAddress address, const QDir recordBaseDir);
|
CJamClient(const qint64 frame, const int numChannels, const QString name, const CHostAddress address, const QDir recordBaseDir);
|
||||||
|
|
||||||
void Frame(const QString name, const CVector<int16_t>& pcm);
|
void Frame(const QString name, const CVector<int16_t>& pcm, int iServerFrameSizeSamples);
|
||||||
|
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ public:
|
||||||
|
|
||||||
CJamSession(QDir recordBaseDir);
|
CJamSession(QDir recordBaseDir);
|
||||||
|
|
||||||
void Frame(const int iChID, const QString name, const CHostAddress address, const int numAudioChannels, const CVector<int16_t> data);
|
void Frame(const int iChID, const QString name, const CHostAddress address, const int numAudioChannels, const CVector<int16_t> data, int iServerFrameSizeSamples);
|
||||||
|
|
||||||
void End();
|
void End();
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ public:
|
||||||
|
|
||||||
void DisconnectClient(int iChID);
|
void DisconnectClient(int iChID);
|
||||||
|
|
||||||
static QMap<QString, QList<STrackItem>> TracksFromSessionDir(const QString& name);
|
static QMap<QString, QList<STrackItem>> TracksFromSessionDir(const QString& name, int iServerFrameSizeSamples);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CJamSession();
|
CJamSession();
|
||||||
|
@ -139,9 +139,10 @@ class CJamRecorder : public QThread
|
||||||
public:
|
public:
|
||||||
CJamRecorder(const QString recordingDirName) :
|
CJamRecorder(const QString recordingDirName) :
|
||||||
recordBaseDir (recordingDirName), isRecording (false) {}
|
recordBaseDir (recordingDirName), isRecording (false) {}
|
||||||
void Init(const CServer* server);
|
|
||||||
|
|
||||||
static void SessionDirToReaper(QString& strSessionDirName);
|
void Init( const CServer* server, const int _iServerFrameSizeSamples );
|
||||||
|
|
||||||
|
static void SessionDirToReaper( QString& strSessionDirName, int serverFrameSizeSamples );
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/**
|
/**
|
||||||
|
@ -170,7 +171,7 @@ private:
|
||||||
|
|
||||||
bool isRecording;
|
bool isRecording;
|
||||||
CJamSession* currentSession;
|
CJamSession* currentSession;
|
||||||
QTextStream& tsConsole = *((new ConsoleWriterFactory())->get());
|
int iServerFrameSizeSamples;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -397,7 +397,7 @@ CServer::CServer ( const int iNewMaxNumChan,
|
||||||
// Enable jam recording (if requested)
|
// Enable jam recording (if requested)
|
||||||
if ( bEnableRecording )
|
if ( bEnableRecording )
|
||||||
{
|
{
|
||||||
JamRecorder.Init ( this );
|
JamRecorder.Init ( this, iServerFrameSizeSamples );
|
||||||
JamRecorder.start();
|
JamRecorder.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue