Logo Search packages:      
Sourcecode: qtractor version File versions

qtractorAudioFile.cpp

// qtractorAudioFile.cpp
//
/****************************************************************************
   Copyright (C) 2005-2006, rncbc aka Rui Nuno Capela. All rights reserved.

   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.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

*****************************************************************************/

#include "qtractorAudioFile.h"
#include "qtractorAudioSndFile.h"
#include "qtractorAudioVorbisFile.h"
#include "qtractorAudioMadFile.h"

#include <QFileInfo>
#include <QRegExp>


//----------------------------------------------------------------------
// class qtractorAudioFileFactory -- Audio file factory (singleton).
//

// Initialize singleton instance pointer.
qtractorAudioFileFactory *qtractorAudioFileFactory::g_pInstance = NULL;


// Singleton instance accessor.
qtractorAudioFileFactory& qtractorAudioFileFactory::getInstance (void)
{
      // Create the singleton instance, if not already...
      if (g_pInstance == NULL) {
            g_pInstance = new qtractorAudioFileFactory();
            std::atexit(Destroy);
      }

      return *g_pInstance;
}


// Singleton instance destroyer.
void qtractorAudioFileFactory::Destroy (void)
{
      // OK. We're done with ourselves.
      if (g_pInstance) {
            qDeleteAll(g_pInstance->m_formats);
            g_pInstance->m_formats.clear();
            g_pInstance->m_filters.clear();
            g_pInstance->m_types.clear();
            delete g_pInstance;
            g_pInstance = NULL;
      }
}


// Constructor.
qtractorAudioFileFactory::qtractorAudioFileFactory (void)
{
      // Default file format/type (for capture/record)
      m_pDefaultFormat  = NULL;
      m_iDefaultFormat  = SF_FORMAT_PCM_16;
      m_iDefaultQuality = 4;

      // Second for libsndfile stuff...
      FileFormat *pFormat;
      const QString sExtMask("*.%1");
      const QString sFilterMask("%1 (%2)");
      SF_FORMAT_INFO sffinfo;
      int iCount = 0;
      ::sf_command(NULL, SFC_GET_FORMAT_MAJOR_COUNT, &iCount, sizeof(int));
      for (int i = 0 ; i < iCount; i++) {
            sffinfo.format = i;
            ::sf_command(NULL, SFC_GET_FORMAT_MAJOR, &sffinfo, sizeof(sffinfo));
            pFormat = new FileFormat;
            pFormat->type = SndFile;
            pFormat->name = QString(sffinfo.name)
                  .replace('/', '-')      // Replace some illegal characters.
                  .replace('(', QString::null)
                  .replace(')', QString::null);
            pFormat->ext  = sffinfo.extension;
            pFormat->data = sffinfo.format;
            m_formats.append(pFormat);
            // Add for the extension map (should be unique)...
            QString sExt = pFormat->ext;
            QString sExts(sExtMask.arg(sExt));
            if (m_types.find(sExt) == m_types.end()) {
                  m_types[sExt] = pFormat;
                  // Take care of some old 8.3 convention,
                  // specially regarding filename extensions...
                  if (sExt.length() > 3) {
                        sExt = sExt.left(3);
                        if (m_types.find(sExt) == m_types.end()) {
                              sExts = sExtMask.arg(sExt) + ' ' + sExts;
                              m_types[sExt] = pFormat;
                        }
                  }
                  // Make a stance on the default format...
                  if (sExt == "wav") m_pDefaultFormat = pFormat;
            }
            // What we see on dialog is some excerpt...
            m_filters.append(
                  sFilterMask.arg(pFormat->name).arg(sExts));
      }

#ifdef CONFIG_LIBVORBIS
      // Add for libvorbis...
      pFormat = new FileFormat;
      pFormat->type = VorbisFile;
      pFormat->name = "OGG Vorbis";
      pFormat->ext  = "ogg";
      pFormat->data = 0;
      m_formats.append(pFormat);
      m_types[pFormat->ext] = pFormat;
      m_filters.append(
            sFilterMask.arg(pFormat->name).arg(sExtMask.arg(pFormat->ext)));
      // Oh yeah, this will be the official default format...
      m_pDefaultFormat = pFormat;
#endif

#ifdef CONFIG_LIBMAD
      // Add for libmad (mp3 read-only)...
      pFormat = new FileFormat;
      pFormat->type = MadFile;
      pFormat->name = "MPEG-1 Audio Layer 3";
      pFormat->ext  = "mp3";
      pFormat->data = 0;
      m_formats.append(pFormat);
      m_types[pFormat->ext] = pFormat;
      m_filters.append(
            sFilterMask.arg(pFormat->name).arg(sExtMask.arg(pFormat->ext)));
#endif

      // Finally, simply build the all supported files entry.
      QRegExp rx("^(aif(|f)|fla(|c)|mp3|ogg|w(av|64))", Qt::CaseInsensitive);
      QStringList exts;
      for (FileTypes::ConstIterator iter = m_types.begin();
                  iter != m_types.end(); ++iter) {
            if (rx.exactMatch(iter.key()))
                  exts.append(sExtMask.arg(iter.key()));
      }
      m_filters.prepend(QObject::tr("Audio Files (%1)").arg(exts.join(" ")));
      m_filters.append(QObject::tr("All Files (*.*)"));
}


// Factory methods.
qtractorAudioFile *qtractorAudioFileFactory::createAudioFile (
      const QString& sFilename, unsigned short iChannels,
      unsigned int iSampleRate, unsigned int iBufferSize )
{
      return getInstance().newAudioFile(
            sFilename, iChannels, iSampleRate, iBufferSize);
}

qtractorAudioFile *qtractorAudioFileFactory::createAudioFile (
      FileType type, unsigned short iChannels,
      unsigned int iSampleRate, unsigned int iBufferSize )
{
      return getInstance().newAudioFile(type, iChannels, iSampleRate, iBufferSize);
}


// Internal factory methods.
qtractorAudioFile *qtractorAudioFileFactory::newAudioFile (
      const QString& sFilename, unsigned short iChannels,
      unsigned int iSampleRate, unsigned int iBufferSize )
{
      const QString sExt = QFileInfo(sFilename).suffix().toLower();
      
      FileTypes::ConstIterator iter = m_types.find(sExt);
      if (iter == m_types.end())
            return NULL;

      return newAudioFile(iter.value()->type, iChannels, iSampleRate, iBufferSize);
}

qtractorAudioFile *qtractorAudioFileFactory::newAudioFile (
      FileType type, unsigned short iChannels,
      unsigned int iSampleRate, unsigned int iBufferSize )
{
      switch (type) {
      case SndFile:
            return new qtractorAudioSndFile(iChannels, iSampleRate, iBufferSize);
      case VorbisFile:
            return new qtractorAudioVorbisFile(iChannels, iSampleRate, iBufferSize);
      case MadFile:
            return new qtractorAudioMadFile(iBufferSize);
      default:
            return NULL;
      }
}


const qtractorAudioFileFactory::FileFormats& qtractorAudioFileFactory::formats (void)
{
      return getInstance().m_formats;
}


// Retrieve supported filters (suitable for QFileDialog usage).
QString qtractorAudioFileFactory::filters (void)
{
      return getInstance().m_filters.join(";;");
}


// Default audio file format accessors
// (specific to capture/recording)
void qtractorAudioFileFactory::setDefaultType(const QString& sExt, int iType,
      int iFormat, int iQuality )
{
      // Search for type-format first...
      int iDefaultFormat = 0;
      QListIterator<FileFormat *> iter(getInstance().m_formats);
      while (iter.hasNext()) {
            FileFormat *pFormat = iter.next();
            if (sExt == pFormat->ext && iType == pFormat->data) {
                  getInstance().m_pDefaultFormat = pFormat;
                  iDefaultFormat = format(pFormat, iFormat);
                  break;
            }
      }

      // Rest is not so obviously trivial...
      getInstance().m_iDefaultFormat  = iDefaultFormat;
      getInstance().m_iDefaultQuality = iQuality;
}


QString qtractorAudioFileFactory::defaultExt (void)
{
      FileFormat *pFormat = getInstance().m_pDefaultFormat;
      if (pFormat)
            return pFormat->ext;

#ifdef CONFIG_LIBVORBIS
      return "ogg";
#else
      return "wav";
#endif
}

int qtractorAudioFileFactory::defaultFormat (void)
{
      int  iDefaultFormat = getInstance().m_iDefaultFormat;
      FileFormat *pFormat = getInstance().m_pDefaultFormat;
      if (pFormat)
            iDefaultFormat |= pFormat->data;
#ifndef CONFIG_LIBVORBIS
      else
            iDefaultFormat |= SF_FORMAT_WAV;
#endif

      return iDefaultFormat;
}


int qtractorAudioFileFactory::defaultQuality (void)
{
      return getInstance().m_iDefaultQuality;
}


// Check whether given file type/format is valid.
bool qtractorAudioFileFactory::isValidFormat (
      const qtractorAudioFileFactory::FileFormat *pFormat, int iFormat )
{
      if (pFormat == NULL)
            return false;

      bool bValid = true;

      // Translate this to some libsndfile slang...
      if (pFormat->type == SndFile) {
            SF_INFO sfinfo;
            ::memset(&sfinfo, 0, sizeof(sfinfo));
            sfinfo.samplerate = 44100;  // Dummy samplerate.
            sfinfo.channels = 2;        // Dummy stereo.
            sfinfo.format = pFormat->data | format(pFormat, iFormat);
            bValid = ::sf_format_check(&sfinfo);
      }

      return bValid;
}


// Translate format index into libsndfile specific...
int qtractorAudioFileFactory::format (
      const qtractorAudioFileFactory::FileFormat *pFormat, int iFormat )
{
      // Translate this to some libsndfile slang...
      if (pFormat && pFormat->type == SndFile) {
            switch (iFormat) {
            case 4:
                  return SF_FORMAT_DOUBLE;
            case 3:
                  return SF_FORMAT_FLOAT;
            case 2:
                  return SF_FORMAT_PCM_32;
            case 1:
                  return SF_FORMAT_PCM_24;
            case 0:
            default:
                  return SF_FORMAT_PCM_16;
            }
      }

      return 0;
}


// end of qtractorAudioFile.cpp

Generated by  Doxygen 1.6.0   Back to index