📄 example2.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 + -