Merge pull request #51 from pljones/multiple-frame-sizes-in-recorder

Multiple frame sizes in recorder
This commit is contained in:
corrados 2020-04-10 19:43:04 +02:00 committed by GitHub
commit 82935c8cd1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 34 deletions

View file

@ -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 << ">";

View file

@ -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:

View file

@ -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 );
} }

View file

@ -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;
}; };
} }

View file

@ -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();
} }