⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 example2.cpp

📁 CDMA 语音编码
💻 CPP
字号:
/******************************************************************************
 ** qscl
 ** Copyright (c) 2003-2004 by QUALCOMM, Inc.  All Rights Reserved
 **
 **     This is the Qualcomm Speech Codec Library, a collection of speech
 **     codecs (encoders and decoders) and associated utilities.  A speech
 **     codec is an algorithm designed to transform speech-oriented audio
 **     between PCM (pulse code modulation) and a compressed format suitable
 **     for transmission over a low-bandwidth link.
 **
 **     The speech codecs available in this library are the ones found on CDMA
 **     and 3G digital cellular networks.
 **
 **     The interfaces provided in this library follow COM-like principles
 **     (Component Object Model) but do not use or require any Microsoft COM
 **     libraries or services.
 **
 ** MODULE
 **     example
 **
 ** DESCRIPTION
 **     This is an example application that uses QSCL to convert a wav file to
 **     a qcp file.  It differs from the first example in that the conversion
 **     is done completely in memory.
 *****************************************************************************/

#define QSCLGUID
#include <qscl.h>
#include <errno.h>
#ifdef WIN32
#include <windows.h>
#elif defined LINUX
#include <dlfcn.h>
#endif /* WIN32 / LINUX */
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <stdexcept>

#ifdef WIN32
#define dlsym GetProcAddress
#define dlerror lastWinError
#define dlclose FreeLibrary
#define LIBHANDLE HMODULE
#elif defined LINUX
#define LIBHANDLE void *
#endif /* WIN32 / LINUX */

using namespace std;

#ifdef WIN32
static string lastWinError ()
/******************************************************************************
 ** This function returns a string describing the last Windows API error.
 **
 ** RETURNS string
 **     A string describing the last Windows API error is returned.
 *****************************************************************************/
{
    LPTSTR lpMsgBuf;
    int size;

    /* Try to convert the error code to a string. */
    FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError (),
        MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf, 0, NULL);

    /* Remove any annoying end-of-line or other non-printable garbage from
    ** the end of the string.
    */
    size = static_cast<int> (strlen (lpMsgBuf));
    while (size && (lpMsgBuf [size - 1] < ' '))
        size--;
    lpMsgBuf [size] = '\0';

    /* Transfer the string to a disposable string object and free
    ** the original buffer.
    */
    string errorString = lpMsgBuf;
    LocalFree (lpMsgBuf);
    return errorString;
}
#endif /* WIN32 */

struct ClientContext
/******************************************************************************
 ** This structure is used to pass context information from the QSCL client,
 ** through the QSCL library, to the client callback function.
 *****************************************************************************/
{
    // Data buffer
    vector<unsigned char> buffer;

    // Current position in buffer
    unsigned long pos;
};

unsigned long qsclClientCallback (QsclClientOp op,
                                  unsigned char *buffer,
                                  unsigned long offset,
                                  unsigned long amount,
                                  void *context)
/******************************************************************************
 ** This callback function is used to interface with a client of the library,
 ** for transferring data.
 **
 ** IN QsclClientOp op
 **     This indicates the operation requested of the client.
 **
 ** unsigned char *buffer
 **     This is the buffer to use, for QSCL_CLIENT_READ and QSCL_CLIENT_WRITE
 **     operations.
 **
 ** unsigned long offset
 **     This is the offset to use, for QSCL_CLIENT_SEEK operations.
 **
 ** unsigned long amount
 **     This is the number of bytes to read, for QSCL_CLIENT_READ operations,
 **     the number of bytes to write, for QSCL_CLIENT_WRITE operations, or the
 **     new size of the file, for QSCL_CLIENT_TRUNCATE.
 **
 ** INOUT void *context
 **     This is the context pointer set in the client handle.
 **
 ** RETURNS unsigned long
 **     The return value depends on the operation requested.  For
 **     QSCL_CLIENT_READ, it is the actual number of bytes read.  For
 **     QSCL_CLIENT_WRITE, it is the actual number of bytes written.  For
 **     QSCL_CLIENT_SEEK, it is the actual position of the file pointer after
 **     the seek operation.
 *****************************************************************************/
{
    // Recover context.
    ClientContext &client = * reinterpret_cast<ClientContext *> (context);

    // Perform requested operation.
    const unsigned long size
        = static_cast<unsigned long> (client.buffer.size ());
    switch (op)
    {
      case QSCL_CLIENT_READ:         /* read data from the client */
          amount = min (amount, size - client.pos);
          copy (&client.buffer [client.pos],
                &client.buffer [client.pos + amount], buffer);
          client.pos += amount;
          return amount;

      case QSCL_CLIENT_WRITE:        /* write data to the client */
          if (client.pos + amount > size)
          {
              client.buffer.resize (client.pos + amount);
          }
          copy (buffer, buffer + amount, &client.buffer [client.pos]);
          client.pos += amount;
          return amount;

      case QSCL_CLIENT_SEEK:         /* seek to new position in data stream */
          client.pos = min (offset, size);
          return client.pos;

      case QSCL_CLIENT_FILE_SIZE:    /* return total size of file in bytes */
          return size;

      case QSCL_CLIENT_TRUNCATE:     /* truncate file at current position */
          client.buffer.resize (client.pos);
          return client.pos;

      default:
          return 0;
    }
}

int main (int argc, const char **argv)
/*****************************************************************************
** This is the main function of the program.  It loads QSCL, creates library
** objects from it, and uses them to convert a wav file to a qcp file.
**
** IN int argc
**     A count of the number of command-line arguments
**
** IN const char **argv
**     A pointer to an array of pointers to the command-line arguments
**
** RETURNS int
**    The value 0 is returned on success, or -1 on failure.
*****************************************************************************/
{
    LIBHANDLE qscl = 0;
    ClientContext wav, qcp;
    try
    {
        // Read test WAV file into memory.
        {
            // Open test WAV file.
            ifstream in ("test.wav", ios::in | ios::binary);
            if (in.fail ())
            {
                ostringstream buf;
                buf << "unable to open input file: " << strerror (errno);
                throw runtime_error (buf.str ());
            }

            // Determine size of file.
            (void) in.seekg (0, ios::end);
            streamsize fileSize = in.tellg ();
            (void) in.seekg (0, ios::beg);

            // Read file into memory buffer.
            wav.buffer.resize (fileSize);
            in.read (reinterpret_cast<char *> (&wav.buffer [0]), fileSize);
            if (in.fail ())
            {
                ostringstream buf;
                buf << "unable to read input file: " << strerror (errno);
                throw runtime_error (buf.str ());
            }
        }

        // Initialize buffer positions.
        wav.pos = 0;
        qcp.pos = 0;

        // Open QSCL.
#ifdef WIN32
        qscl = LoadLibrary ("qscl.dll");
#elif defined LINUX
        qscl = dlopen ("libqscl.so.1", RTLD_LAZY);
#endif /* WIN32 / LINUX */
        if (!qscl)
        {
            ostringstream buf;
            buf << "unable to load QSCL: " << dlerror ();
            throw runtime_error (buf.str ());
        }

        // Map address of class factory.
        void * (*ci) (const QsclGuid &classId,
                      const QsclGuid &ifId)
            = (void * (*) (const QsclGuid &, const QsclGuid &))
            (dlsym (qscl, "QsclCreateInstance"));
        if (!ci)
        {
            ostringstream buf;
            buf << "unable to access QSCL class factory: " << dlerror ();
            throw runtime_error (buf.str ());
        }

        // Create converter object.
        IQsclConvertFile *cf = reinterpret_cast<IQsclConvertFile *>
            (ci (ID_QsclFile, ID_IQsclConvertFile));
        if (!cf)
        {
            ostringstream buf;
            buf << "unable to create file converter object";
            throw runtime_error (buf.str ());
        }

        // Set up file converter arguments.
        QsclHandle inHandle;
        QsclHandle outHandle;
        QsclSpeechInfo inFormat;
        QsclSpeechInfo outFormat;
        inHandle.client.type = QSCL_HANDLE_CLIENT;
        inHandle.client.cb = qsclClientCallback;
        inHandle.client.context = &wav;
        outHandle.client.type = QSCL_HANDLE_CLIENT;
        outHandle.client.cb = qsclClientCallback;
        outHandle.client.context = &qcp;
        inFormat.format = ID_FormatWav;
        inFormat.codec = ID_QsclCodecPcm;
        inFormat.samplesPerSecond = 8000;
        inFormat.bitsPerSample = 16;
        outFormat.format = ID_FormatQcp;
        outFormat.codec = ID_QsclCodecQcelp;
        outFormat.rateSet = ID_RateVariable;

        // Convert the file.
        cout << "Converting wav ("
             << static_cast<unsigned long> (wav.buffer.size ())
             << " bytes) to qcp in memory" << endl;
        if (!cf->convertFile (inHandle, inFormat, outHandle, outFormat))
        {
            ostringstream buf;
            buf << "unable to convert wav buffer to qcp buffer";
            IQsclError *error = reinterpret_cast<IQsclError *>
                (cf->queryInterface (ID_IQsclError));
            if (error && error->wasLastError ())
            {
                buf << ": " << error->getLastError ();
                error->release ();
            }
            throw runtime_error (buf.str ());
        }
        cf->release ();

        // Create file reader object.
        IQsclFile *reader = reinterpret_cast<IQsclFile *>
            (ci (ID_QsclFile, ID_IQsclFile));
        if (!reader)
        {
            ostringstream buf;
            buf << "ERROR: unable to create file reader object" << endl;
            throw runtime_error (buf.str ());
        }

        // Reopen file and print out its length.
        if (!reader->open (outHandle, false, outFormat, outFormat))
        {
            ostringstream buf;
            buf << "ERROR: unable to open converted file" << endl;
            throw runtime_error (buf.str ());
        }
        QsclSpeechInfo info;
        reader->getInfo (info);
        cout << "Converted qcp is "
             << reader->getFileSize () * info.samplesPerBlock / 8
             << " ms long" << endl;
        reader->release ();

        // Save qcp output to a real file.
        {
            // Open output file.
            ofstream out ("test.qcp", ios::out | ios::binary
                          | ios::trunc);
            if (out.fail ())
            {
                ostringstream buf;
                buf << "unable to open output file: " << strerror (errno);
                throw runtime_error (buf.str ());
            }

            // Write qcp buffer to the file.
            out.write (reinterpret_cast<const char *> (&qcp.buffer [0]),
                       static_cast<streamsize> (qcp.buffer.size ()));
            if (out.fail ())
            {
                ostringstream buf;
                buf << "unable to write output file: " << strerror (errno);
                throw runtime_error (buf.str ());
            }
        }
    }
    catch (exception &e)
    {
        cerr << "ERROR: " << e.what () << endl;
    }

    // Close QSCL.
    if (qscl)
    {
        (void) dlclose (qscl);
    }
    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -