summaryrefslogtreecommitdiff
path: root/orkbasecxx/audiofile
diff options
context:
space:
mode:
Diffstat (limited to 'orkbasecxx/audiofile')
-rw-r--r--orkbasecxx/audiofile/AudioFile.cpp63
-rw-r--r--orkbasecxx/audiofile/AudioFile.h71
-rw-r--r--orkbasecxx/audiofile/LibSndFileFile.cpp138
-rw-r--r--orkbasecxx/audiofile/LibSndFileFile.h46
-rw-r--r--orkbasecxx/audiofile/Makefile.am6
-rw-r--r--orkbasecxx/audiofile/MediaChunkFile.cpp154
-rw-r--r--orkbasecxx/audiofile/MediaChunkFile.h40
-rw-r--r--orkbasecxx/audiofile/PcmFile.cpp117
-rw-r--r--orkbasecxx/audiofile/PcmFile.h41
9 files changed, 676 insertions, 0 deletions
diff --git a/orkbasecxx/audiofile/AudioFile.cpp b/orkbasecxx/audiofile/AudioFile.cpp
new file mode 100644
index 0000000..848f55b
--- /dev/null
+++ b/orkbasecxx/audiofile/AudioFile.cpp
@@ -0,0 +1,63 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "AudioFile.h"
+#include "ace/OS_NS_unistd.h"
+
+void AudioFile::Open(fileOpenModeEnum mode, bool stereo , int sampleRate)
+{
+ Open(m_filename, mode, stereo, sampleRate);
+}
+
+
+void AudioFile::RecursiveMkdir(CStdString& path)
+{
+ int position = 0;
+ bool done = false;
+ while (!done)
+ {
+ position = path.Find('/', position+1);
+ if (position == -1)
+ {
+ done = true;
+ }
+ else
+ {
+ CStdString level = path.Left(position);
+ ACE_OS::mkdir((PCSTR)level);
+ }
+ }
+}
+
+void AudioFile::MoveOrig()
+{
+ CStdString newName = m_filename + ".orig";
+ if (ACE_OS::rename((PCSTR)m_filename, (PCSTR)newName) == 0)
+ {
+ m_filename = newName;
+ }
+ else
+ {
+ throw(CStdString("AudioFile::MoveOrig: could not rename file:" + m_filename));
+ }
+}
+
+void AudioFile::Delete()
+{
+ ACE_OS::unlink((PCSTR)m_filename);
+}
+
+int AudioFile::GetSampleRate()
+{
+ return m_sampleRate;
+} \ No newline at end of file
diff --git a/orkbasecxx/audiofile/AudioFile.h b/orkbasecxx/audiofile/AudioFile.h
new file mode 100644
index 0000000..bc9cbcf
--- /dev/null
+++ b/orkbasecxx/audiofile/AudioFile.h
@@ -0,0 +1,71 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#ifndef __AUDIOFILE_H__
+#define __AUDIOFILE_H__
+
+#include "boost/shared_ptr.hpp"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_sys_stat.h"
+
+#include "StdString.h"
+#include "AudioCapture.h"
+
+
+/** Base class for all file accessor classes. */
+class AudioFile
+{
+public:
+ typedef enum {READ = 0, WRITE = 1} fileOpenModeEnum;
+
+ /** Open audio file for reading or writing.
+ Filename should include path information but not extension (which is automatically appended)
+ If the underlying format does not support stereo, data is transparently read from two files in read mode
+ or two files are transparently written to in write mode */
+ virtual void Open(CStdString& filename, fileOpenModeEnum mode, bool stereo = false, int sampleRate = 8000) = 0;
+ /** Same as above but uses the intenal filename */
+ void Open(fileOpenModeEnum mode, bool stereo = false, int sampleRate = 8000);
+ /** Explicitely close the underlying file(s). This is also done automatically by the destructor */
+ virtual void Close() = 0;
+
+ /** Writes a chunk of audio to disk.
+ If stereo capture, this represents the local party */
+ virtual void WriteChunk(AudioChunkRef chunkRef) = 0;
+ /** Writes a chunk of audio from the remote pary to disk (if stereo capture)
+ //virtual bool WriteRemoteChunk(AudioChunkRef chunkRef) = 0;
+ /** Reads a chunk of audio stereo-wise
+ If underlying storage is mono, remoteChunk will be NULL
+ ReadChunkStereo guarantees that local and remote chunks returned are in sync */
+ //virtual bool ReadChunkStereo(AudioChunkRef& chunk, AudioChunkRef& remoteChunk) = 0;
+ /** Reads a chunk of audio mono-wise
+ If underlying file is stereo, ReadChunkMono merges the two streams in a synchronized manner and returns the result */
+ virtual int ReadChunkMono(AudioChunkRef& chunk) = 0;
+
+ /** Move the file to a new name including ".orig" suffix */
+ void MoveOrig();
+ void Delete();
+ virtual CStdString GetExtension() = 0;
+ virtual int GetSampleRate();
+
+ static void RecursiveMkdir(CStdString& path);
+protected:
+ CStdString m_filename;
+ fileOpenModeEnum m_mode;
+ int m_numChunksWritten;
+ int m_sampleRate;
+};
+
+typedef boost::shared_ptr<AudioFile> AudioFileRef;
+
+#endif
+
diff --git a/orkbasecxx/audiofile/LibSndFileFile.cpp b/orkbasecxx/audiofile/LibSndFileFile.cpp
new file mode 100644
index 0000000..0589466
--- /dev/null
+++ b/orkbasecxx/audiofile/LibSndFileFile.cpp
@@ -0,0 +1,138 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#define _WINSOCKAPI_ // prevents the inclusion of winsock.h
+
+#include "Utils.h"
+#include "LibSndFileFile.h"
+
+LibSndFileFile::LibSndFileFile(int fileFormat)
+{
+ m_fileInfo.format = fileFormat;
+ m_fileInfo.frames = 0;
+ m_fileInfo.samplerate = 0;
+ m_fileInfo.channels = 0;
+ m_fileInfo.sections = 0;
+ m_fileInfo.seekable = 0;
+ m_pFile = NULL;
+ m_numChunksWritten = 0;
+ m_mode = READ;
+ m_sampleRate = 0;
+}
+
+LibSndFileFile::~LibSndFileFile()
+{
+ Close();
+}
+
+void LibSndFileFile::Open(CStdString& filename, fileOpenModeEnum mode, bool stereo, int sampleRate)
+{
+ if(!m_filename.Equals(filename))
+ {
+ m_filename = filename + ".wav";
+ }
+ m_mode = mode;
+ stereo ? m_fileInfo.channels = 2 : m_fileInfo.channels = 1;
+ if(m_sampleRate == 0)
+ {
+ m_sampleRate = sampleRate;
+ m_fileInfo.samplerate = sampleRate;
+ }
+
+ if( (mode==WRITE) && !sf_format_check(&m_fileInfo))
+ {
+ throw(CStdString("libsndfile: Selected output format not supported"));
+ }
+
+ RecursiveMkdir(m_filename);
+
+ int sndFileMode;
+ mode == READ ? sndFileMode = SFM_READ : sndFileMode = SFM_WRITE;
+ m_pFile = sf_open((PCSTR)m_filename, sndFileMode, &m_fileInfo);
+
+ if(!m_pFile)
+ {
+ throw(CStdString("sf_open failed, audio file could not be created:"+ m_filename));
+ }
+}
+
+void LibSndFileFile::WriteChunk(AudioChunkRef chunkRef)
+{
+ if(chunkRef.get() == NULL)
+ {
+ return;
+ }
+ if(chunkRef->GetDetails()->m_numBytes == 0)
+ {
+ return;
+ }
+
+ if (m_pFile)
+ {
+ if( chunkRef->GetEncoding() == AlawAudio || chunkRef->GetEncoding() == UlawAudio)
+ {
+ if(sf_write_raw(m_pFile, chunkRef->m_pBuffer, chunkRef->GetNumSamples()) != chunkRef->GetNumSamples())
+ {
+ CStdString numChunksWrittenString = IntToString(m_numChunksWritten);
+ throw(CStdString("sf_write_raw failed, audio file " + m_filename + " could not be written after " + numChunksWrittenString + " chunks written"));
+ }
+ }
+ else if (chunkRef->GetEncoding() == PcmAudio)
+ {
+ if(sf_write_short(m_pFile, (short*)chunkRef->m_pBuffer, chunkRef->GetNumSamples()) != chunkRef->GetNumSamples())
+ {
+ CStdString numChunksWrittenString = IntToString(m_numChunksWritten);
+ throw(CStdString("sf_write_short failed, audio file " + m_filename + " could not be written after " + numChunksWrittenString + " chunks written"));
+ }
+ }
+ m_numChunksWritten++;
+ }
+ else
+ {
+ throw(CStdString("Write attempt on unopened file:")+ m_filename);
+ }
+}
+
+int LibSndFileFile::ReadChunkMono(AudioChunkRef& chunk)
+{
+ unsigned int numRead = 0;
+ if (m_pFile)
+ {
+ chunk.reset(new AudioChunk());
+ short temp[8000];
+ numRead = sf_read_short(m_pFile, temp, 8000);
+ AudioChunkDetails details;
+ details.m_encoding = PcmAudio;
+ chunk->SetBuffer(temp, sizeof(short)*numRead, details);
+ }
+ else
+ {
+ throw(CStdString("Read attempt on unopened file:")+ m_filename);
+ }
+ return numRead;
+}
+
+
+void LibSndFileFile::Close()
+{
+ if (m_pFile)
+ {
+ sf_close(m_pFile);
+ m_pFile = NULL;
+ }
+}
+
+CStdString LibSndFileFile::GetExtension()
+{
+ return ".wav";
+}
diff --git a/orkbasecxx/audiofile/LibSndFileFile.h b/orkbasecxx/audiofile/LibSndFileFile.h
new file mode 100644
index 0000000..e0516a8
--- /dev/null
+++ b/orkbasecxx/audiofile/LibSndFileFile.h
@@ -0,0 +1,46 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#ifndef __LIBSNDFILEFILE_H__
+#define __LIBSNDFILEFILE_H__
+
+
+#include "StdString.h"
+#include "AudioCapture.h"
+#include "sndfile.h"
+#include "AudioFile.h"
+
+
+/** file accessor class for all file types supported by the libsndfile library.
+ The library can be found at http://www.mega-nerd.com/libsndfile/
+*/
+class LibSndFileFile : public AudioFile
+{
+public:
+ LibSndFileFile(int fileFormat); // fileFormat is described at http://www.mega-nerd.com/libsndfile/api.html
+ ~LibSndFileFile();
+
+ void Open(CStdString& filename, fileOpenModeEnum mode, bool stereo = false, int sampleRate = 8000);
+ void Close();
+
+ void WriteChunk(AudioChunkRef chunkRef);
+ int ReadChunkMono(AudioChunkRef& chunk);
+
+ CStdString GetExtension();
+private:
+ SF_INFO m_fileInfo;
+ SNDFILE* m_pFile;
+};
+
+#endif
+
diff --git a/orkbasecxx/audiofile/Makefile.am b/orkbasecxx/audiofile/Makefile.am
new file mode 100644
index 0000000..d737e11
--- /dev/null
+++ b/orkbasecxx/audiofile/Makefile.am
@@ -0,0 +1,6 @@
+METASOURCES = AUTO
+noinst_LTLIBRARIES = libaudiofile.la
+libaudiofile_la_SOURCES = MediaChunkFile.cpp AudioFile.cpp LibSndFileFile.cpp PcmFile.cpp
+AM_CPPFLAGS = -D_REENTRANT
+libaudiofile_la_LIBADD =
+INCLUDES = -I@top_srcdir@ -I../../orkbasecxx
diff --git a/orkbasecxx/audiofile/MediaChunkFile.cpp b/orkbasecxx/audiofile/MediaChunkFile.cpp
new file mode 100644
index 0000000..47b2e8b
--- /dev/null
+++ b/orkbasecxx/audiofile/MediaChunkFile.cpp
@@ -0,0 +1,154 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "MediaChunkFile.h"
+
+#define MAX_CHUNK_SIZE 100000
+
+
+MediaChunkFile::MediaChunkFile()
+{
+ m_stream = NULL;
+ m_mode = READ;
+ m_numChunksWritten = 0;
+ m_sampleRate = 0;
+}
+
+MediaChunkFile::~MediaChunkFile()
+{
+ Close();
+}
+
+
+void MediaChunkFile::Close()
+{
+ if(m_stream)
+ {
+ ACE_OS::fclose(m_stream);
+ m_stream = NULL;
+ }
+}
+
+void MediaChunkFile::WriteChunk(AudioChunkRef chunkRef)
+{
+ if(chunkRef.get() == NULL)
+ {
+ return;
+ }
+ if(chunkRef->GetDetails()->m_numBytes == 0)
+ {
+ return;
+ }
+
+ unsigned int numWritten = 0;
+ bool writeError = false;
+ if (m_stream)
+ {
+ int tmp = sizeof(AudioChunkDetails);
+ numWritten = ACE_OS::fwrite(chunkRef->GetDetails(), sizeof(AudioChunkDetails), 1, m_stream);
+ if(numWritten != 1)
+ {
+ writeError = true;
+ }
+ numWritten = ACE_OS::fwrite(chunkRef->m_pBuffer, sizeof(char), chunkRef->GetNumBytes(), m_stream);
+ if(numWritten != chunkRef->GetNumBytes())
+ {
+ writeError = true;
+ }
+ }
+ else
+ {
+ throw(CStdString("Write attempt on unopened file:")+ m_filename);
+ }
+
+ if (writeError)
+ {
+ throw(CStdString("Could not write to file:")+ m_filename);
+ }
+}
+
+int MediaChunkFile::ReadChunkMono(AudioChunkRef& chunkRef)
+{
+ unsigned int numRead = 0;
+ bool readError = false;
+
+ if (m_stream)
+ {
+ chunkRef.reset(new AudioChunk());
+ short temp[MAX_CHUNK_SIZE];
+ numRead = ACE_OS::fread(temp, sizeof(AudioChunkDetails), 1, m_stream);
+ if(numRead == 1)
+ {
+ AudioChunkDetails details;
+ memcpy(&details, temp, sizeof(AudioChunkDetails));
+
+ if(details.m_marker != MEDIA_CHUNK_MARKER)
+ {
+ throw(CStdString("Invalid marker in file:")+ m_filename);
+ }
+ if(details.m_numBytes >= MAX_CHUNK_SIZE)
+ {
+ throw(CStdString("Chunk too big in file:")+ m_filename);
+ }
+ else
+ {
+ numRead = ACE_OS::fread(temp, sizeof(char), details.m_numBytes, m_stream);
+ if(numRead != details.m_numBytes)
+ {
+ throw(CStdString("Incomplete chunk in file:")+ m_filename);
+ }
+ chunkRef->SetBuffer(temp, details.m_numBytes, details);
+ }
+ }
+ }
+ else
+ {
+ throw(CStdString("Read attempt on unopened file:")+ m_filename);
+ }
+
+ return numRead;
+}
+
+
+void MediaChunkFile::Open(CStdString& filename, fileOpenModeEnum mode, bool stereo, int sampleRate)
+{
+ if(m_sampleRate == 0)
+ {
+ m_sampleRate = sampleRate;
+ }
+
+ if(!m_filename.Equals(filename))
+ {
+ m_filename = filename + GetExtension();
+ }
+ m_stream = NULL;
+ m_mode = mode;
+ if (mode == READ)
+ {
+ m_stream = ACE_OS::fopen((PCSTR)m_filename, "rb");
+ }
+ else
+ {
+ RecursiveMkdir(m_filename);
+ m_stream = ACE_OS::fopen((PCSTR)m_filename, "wb");
+ }
+ if(!m_stream)
+ {
+ throw(CStdString("Could not open file: ") + m_filename);
+ }
+}
+
+CStdString MediaChunkFile::GetExtension()
+{
+ return ".mcf";
+}
diff --git a/orkbasecxx/audiofile/MediaChunkFile.h b/orkbasecxx/audiofile/MediaChunkFile.h
new file mode 100644
index 0000000..b8e69ed
--- /dev/null
+++ b/orkbasecxx/audiofile/MediaChunkFile.h
@@ -0,0 +1,40 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#ifndef __MEDIACHUNKFILE_H__
+#define __MEDIACHUNKFILE_H__
+
+#include "audiofile/AudioFile.h"
+
+
+/** File class for saving audio chunks as-is */
+class MediaChunkFile : public AudioFile
+{
+public:
+ MediaChunkFile();
+ ~MediaChunkFile();
+
+ void Open(CStdString& filename, fileOpenModeEnum mode, bool stereo = false, int sampleRate = 8000);
+ void Close();
+
+ void WriteChunk(AudioChunkRef chunkRef);
+ int ReadChunkMono(AudioChunkRef& chunkRef);
+
+ CStdString GetExtension();
+protected:
+
+ FILE* m_stream;
+};
+
+#endif
+
diff --git a/orkbasecxx/audiofile/PcmFile.cpp b/orkbasecxx/audiofile/PcmFile.cpp
new file mode 100644
index 0000000..9d1a6d0
--- /dev/null
+++ b/orkbasecxx/audiofile/PcmFile.cpp
@@ -0,0 +1,117 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "PcmFile.h"
+
+PcmFile::PcmFile()
+{
+ m_stream = NULL;
+ m_mode = READ;
+ m_numChunksWritten = 0;
+ m_sampleRate = 0;
+}
+
+PcmFile::~PcmFile()
+{
+ Close();
+}
+
+
+void PcmFile::Close()
+{
+ if(m_stream)
+ {
+ ACE_OS::fclose(m_stream);
+ m_stream = NULL;
+ }
+}
+
+void PcmFile::WriteChunk(AudioChunkRef chunkRef)
+{
+ if(chunkRef.get() == NULL)
+ {
+ return;
+ }
+ if(chunkRef->GetDetails()->m_numBytes == 0)
+ {
+ return;
+ }
+
+ unsigned int numWritten = 0;
+ if (m_stream)
+ {
+ numWritten = ACE_OS::fwrite(chunkRef->m_pBuffer, sizeof(short), chunkRef->GetNumSamples(), m_stream);
+ }
+ else
+ {
+ throw(CStdString("Write attempt on unopened file:")+ m_filename);
+ }
+
+ if (numWritten != chunkRef->GetNumSamples())
+ {
+ throw(CStdString("Could not write to file:")+ m_filename);
+ }
+}
+
+int PcmFile::ReadChunkMono(AudioChunkRef& chunkRef)
+{
+ unsigned int numRead = 0;
+ if (m_stream)
+ {
+ chunkRef.reset(new AudioChunk());
+ short temp[PCM_FILE_DEFAULT_CHUNK_NUM_SAMPLES];
+ numRead = ACE_OS::fread(temp, sizeof(short), PCM_FILE_DEFAULT_CHUNK_NUM_SAMPLES, m_stream);
+ AudioChunkDetails details;
+ details.m_encoding = PcmAudio;
+ chunkRef->SetBuffer(temp, sizeof(short)*numRead, details);
+ }
+ else
+ {
+ throw(CStdString("Read attempt on unopened file:")+ m_filename);
+ }
+ return numRead;
+}
+
+
+void PcmFile::Open(CStdString& filename, fileOpenModeEnum mode, bool stereo, int sampleRate)
+{
+ if(m_sampleRate == 0)
+ {
+ m_sampleRate = sampleRate;
+ }
+
+ if(!m_filename.Equals(filename))
+ {
+ m_filename = filename + ".pcm";
+ }
+ m_stream = NULL;
+ m_mode = mode;
+ if (mode == READ)
+ {
+ m_stream = ACE_OS::fopen((PCSTR)m_filename, "rb");
+ }
+ else
+ {
+ RecursiveMkdir(m_filename);
+ m_stream = ACE_OS::fopen((PCSTR)m_filename, "wb");
+ }
+ if(!m_stream)
+ {
+ throw(CStdString("Could not open file: ") + m_filename);
+ }
+}
+
+CStdString PcmFile::GetExtension()
+{
+ return ".pcm";
+}
diff --git a/orkbasecxx/audiofile/PcmFile.h b/orkbasecxx/audiofile/PcmFile.h
new file mode 100644
index 0000000..91c1325
--- /dev/null
+++ b/orkbasecxx/audiofile/PcmFile.h
@@ -0,0 +1,41 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#ifndef __PCMFILE_H__
+#define __PCMFILE_H__
+
+#include "audiofile/AudioFile.h"
+
+#define PCM_FILE_DEFAULT_CHUNK_NUM_SAMPLES 8000
+
+/** File class for raw 16 bit signed PCM output */
+class PcmFile : public AudioFile
+{
+public:
+ PcmFile();
+ ~PcmFile();
+
+ void Open(CStdString& filename, fileOpenModeEnum mode, bool stereo = false, int sampleRate = 8000);
+ void Close();
+
+ void WriteChunk(AudioChunkRef chunkRef);
+ int ReadChunkMono(AudioChunkRef& chunkRef);
+
+ CStdString GetExtension();
+protected:
+
+ FILE* m_stream;
+};
+
+#endif
+