如何运行以下代码

时间:2015-12-08 07:57:59

标签: c++ audio

我有一个相对较大的C ++项目,我正试图弄清楚如何运行。 下面列出了3个代码文件和2个.wav音频文件 - test.wav和poolIR.wav。

程序应该将测试文件与脉冲响应进行卷积并生成第三个输出文件。这两个音频文件必须在运行时传递给程序,我是C / C ++的新手,所以我试着看看我应该怎么做。请有人帮帮我。以下是代码。

我使用的是WINDOWS 7,我安装了gcc。

convolve.cpp:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fstream>
#include <iostream>
#include <math.h>
#include "CWav.h"

using namespace std;

#define DEBUG_MODE

/*  Test tone frequency in Hz  */
#define FREQUENCY           440.0

/*  Test tone duration in seconds  */
#define DURATION            2.0             

/*  Standard sample rate in Hz  */
#define SAMPLE_RATE         44100.0

/*  Standard sample size in bits  */
#define BITS_PER_SAMPLE     16

/*  Standard sample size in bytes  */       
#define BYTES_PER_SAMPLE    (BITS_PER_SAMPLE/8)

/*  Number of channels  */
#define MONOPHONIC          1
#define STEREOPHONIC        2

#define SIZE       8
#define PI         3.141592653589793
#define TWO_PI     (2.0 * PI)
#define SWAP(a,b)  tempr=(a);(a)=(b);(b)=tempr


void outputToFile(double data[], CWav* original , int numberOfSamples, char* outputFile);
void four1(double data[], int nn, int isign);
void writeWaveFileHeader(int channels, int numberSamples, int bitsPerSample, double sampleRate, FILE *outputFile);
size_t fwriteIntLSB(int data, FILE *stream);
void getSignal(CWav *input, double x[]);
size_t fwriteShortLSB(short int data, FILE *stream);
void outputToFile(double data[], CWav* original , int numberOfSamples, char* outputFile);


//  The four1 FFT from Numerical Recipes in C,
//  p. 507 - 508.
//  Note:  changed float data types to double.
//  nn must be a power of 2, and use +1 for
//  isign for an FFT, and -1 for the Inverse FFT.
//  The data is complex, so the array size must be
//  nn*2. This code assumes the array starts
//  at index 1, not 0, so subtract 1 when
//  calling the routine (see main() below).

void four1(double data[], int nn, int isign)
{
    unsigned long n, mmax, m, j, istep, i;
    double wtemp, wr, wpr, wpi, wi, theta;
    double tempr, tempi;

    n = nn << 1;
    j = 1;

    for (i = 1; i < n; i += 2) {
    if (j > i) {
        SWAP(data[j], data[i]);
        SWAP(data[j+1], data[i+1]);
    }
    m = nn;
    while (m >= 2 && j > m) {
        j -= m;
        m >>= 1;
    }
    j += m;
    }

    mmax = 2;
    while (n > mmax) {
    istep = mmax << 1;
    theta = isign * (6.28318530717959 / mmax);
    wtemp = sin(0.5 * theta);
    wpr = -2.0 * wtemp * wtemp;
    wpi = sin(theta);
    wr = 1.0;
    wi = 0.0;
    for (m = 1; m < mmax; m += 2) {
        for (i = m; i <= n; i += istep) {
        j = i + mmax;
        tempr = wr * data[j] - wi * data[j+1];
        tempi = wr * data[j+1] + wi * data[j];
        data[j] = data[i] - tempr;
        data[j+1] = data[i+1] - tempi;
        data[i] += tempr;
        data[i+1] += tempi;
        }
        wr = (wtemp = wr) * wpr - wi * wpi + wr;
        wi = wi * wpr + wtemp * wpi + wi;
    }
    mmax = istep;
    }
}

void writeWaveFileHeader(int channels, int numberSamples, int bitsPerSample,
                         double sampleRate, FILE *outputFile)
{
    /*  Calculate the total number of bytes for the data chunk  */
    int dataChunkSize = channels * numberSamples * (bitsPerSample / 8);

    /*  Calculate the total number of bytes for the form size  */
    int formSize = 36 + dataChunkSize;

    /*  Calculate the total number of bytes per frame  */
    short int frameSize = channels * (bitsPerSample / 8);

    /*  Calculate the byte rate  */
    int bytesPerSecond = (int)ceil(sampleRate * frameSize);

    /*  Write header to file  */
    /*  Form container identifier  */
    fputs("RIFF", outputFile);

    /*  Form size  */
    fwriteIntLSB(formSize, outputFile);

    /*  Form container type  */
    fputs("WAVE", outputFile);

    /*  Format chunk identifier (Note: space after 't' needed)  */
    fputs("fmt ", outputFile);

    /*  Format chunk size (fixed at 16 bytes)  */
    fwriteIntLSB(16, outputFile);

    /*  Compression code:  1 = PCM  */
    fwriteShortLSB(1, outputFile);

    /*  Number of channels  */
    fwriteShortLSB((short)channels, outputFile);

    /*  Output Sample Rate  */
    fwriteIntLSB((int)sampleRate, outputFile);

    /*  Bytes per second  */
    fwriteIntLSB(bytesPerSecond, outputFile);

    /*  Block alignment (frame size)  */
    fwriteShortLSB(frameSize, outputFile);

    /*  Bits per sample  */
    fwriteShortLSB(bitsPerSample, outputFile);

    /*  Sound Data chunk identifier  */
    fputs("data", outputFile);

    /*  Chunk size  */
    fwriteIntLSB(dataChunkSize, outputFile);
}



/******************************************************************************
 *
 *       function:       fwriteIntLSB
 *
 *       purpose:        Writes a 4-byte integer to the file stream, starting
 *                       with the least significant byte (i.e. writes the int
 *                       in little-endian form).  This routine will work on both
 *                       big-endian and little-endian architectures.
 *
 *       internal
 *       functions:      none
 *
 *       library
 *       functions:      fwrite
 *
 ******************************************************************************/

size_t fwriteIntLSB(int data, FILE *stream)
{
    unsigned char array[4];

    array[3] = (unsigned char)((data >> 24) & 0xFF);
    array[2] = (unsigned char)((data >> 16) & 0xFF);
    array[1] = (unsigned char)((data >> 8) & 0xFF);
    array[0] = (unsigned char)(data & 0xFF);
    return fwrite(array, sizeof(unsigned char), 4, stream);
}



/******************************************************************************
 *
 *       function:       fwriteShortLSB
 *
 *       purpose:        Writes a 2-byte integer to the file stream, starting
 *                       with the least significant byte (i.e. writes the int
 *                       in little-endian form).  This routine will work on both
 *                       big-endian and little-endian architectures.
 *
 *       internal
 *       functions:      none
 *
 *       library
 *       functions:      fwrite
 *
 ******************************************************************************/

size_t fwriteShortLSB(short int data, FILE *stream)
{
    unsigned char array[2];

    array[1] = (unsigned char)((data >> 8) & 0xFF);
    array[0] = (unsigned char)(data & 0xFF);
    return fwrite(array, sizeof(unsigned char), 2, stream);
}

void getSignal(CWav *input, double x[]) {
    for ( int i = 0; i < input->mySignalSize; i++ ) 
        x[i] = ((double)input->my_signal[i])/32678.0;
}

void outputToFile(double output_signal[], CWav* original , int numberOfSamples, char* outputFile) {

    /*  Open a binary output file stream for writing */
    FILE *outputFileStream = fopen(outputFile, "wb");

    /*  Write the WAVE file header  */
    writeWaveFileHeader(original->myChannels, numberOfSamples, original->myBitsPerSample,
                        original->mySampleRate, outputFileStream);

    int i;
    float maxValInResult = -1.0;
    for (i = 0; i < numberOfSamples; i++ )
        if ( output_signal[i] > maxValInResult )
            maxValInResult = output_signal[i];

    float maxValInInput = -1.0;
    for (i = 0; i < numberOfSamples; i++ )
        if (original->my_signal[i] > maxValInInput )
            maxValInInput = original->my_signal[i];

    for (i = 0; i < numberOfSamples; i++ )
        fwriteShortLSB((short)(output_signal[i] / maxValInResult * maxValInInput), outputFileStream);


    /*  Close the output file stream  */
    fclose(outputFileStream);
}
//convolve inputfile IRfile outputfile as inputs to main
int main(int argc, char* argv[])
{
    if (argc != 4) {
        cout << "USAGE: ./convolve inputfile IRfile outputfile" << endl;
        //system("PAUSE");
        return 0;
    }
        cout << argv[0] << endl;
        cout << "Input File:" << argv[1] << endl;
        cout << "IRfile:" << argv[2] << endl;
        cout << "outputfile File:" <<argv[3] << endl;


    char *outputFilename = argv[3];

    /*  Create the sine wave test tone, using the specified
     frequency, duration, and number of channels, writing to
     a .wav file with the specified output filename  */

    //createTestTone(FREQUENCY, DURATION, MONOPHONIC, BITS_PER_SAMPLE, SAMPLE_RATE, outputFilename);

    CWav *inputSignal = new CWav();
    inputSignal->readInput(argv[1]);

    //manipulate(inputSignal, 2);

    CWav *impulse = new CWav();
    impulse->readInput(argv[2]);

    cout << "Input Signal: " << inputSignal->mySignalSize << ", Impulse Size: " << impulse->mySignalSize << endl;

    double h[impulse->mySignalSize];
    double x[inputSignal->mySignalSize];

    getSignal(impulse, h);  
    getSignal(inputSignal, x);  


    int sizeH = impulse->mySignalSize;
    int sizeX = inputSignal->mySignalSize;

    cout << "SIZES(H,X)" << endl;
    cout << sizeH << endl;
    cout << sizeX << endl;

    int maxSize = 0;
    if(sizeX >= sizeH) {
        maxSize = sizeX;
    }
    else {
        maxSize = sizeH;
    }
    cout << "maxSize: " << maxSize << endl;

    int power = 0;  
    int pow2 = 0;

    pow2 = (int) log2(maxSize) + 1;
    pow2 = pow(2,pow2);

    cout << "POW :" << pow2 << endl;

    int i = 0;

    int doublePow2 = 2 * pow2;
    //set hComplex with 0's
    double hComplex[doublePow2];
    double *xComplex = new double[doublePow2];
    //set hComplex , xComplex with 0's
    for(i = 0; i < doublePow2; i++) {
        hComplex[i] = 0.0;          
        xComplex[i] = 0.0;
    }   

    //padding the complex number with 0 and the real number with original value for h
    for(i = 0; i < sizeH; i++) {
        hComplex[2*i] = h[i];
    }

    //padding the complex number with 0 and the real number with original value for x
    for(i = 0; i < sizeX; i++) {
        xComplex[2*i] = x[i];
    }


    four1(hComplex, pow2, 1);
    four1(xComplex, pow2, 1);

    double *yComplex = new double[doublePow2];      
    for(i = 0; i < pow2 ; i++) {
        yComplex[i*2] = xComplex[i] * hComplex[i] - xComplex[i+1] * hComplex[i+1];
        yComplex[i*2+1] = xComplex[i+1] * hComplex[i] + xComplex[i] * hComplex[i+1];
    }

    four1(yComplex-1, pow2, -1);
    outputToFile(yComplex, inputSignal, pow2, outputFilename);
}

CWav.cpp:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fstream>
#include <iostream>

#include "CWav.h"

using namespace std;

void CWav::readInput(char *filename)
{

    ifstream inFile( filename, ios::in | ios::binary);

    //printf("Reading wav file...\n"); // for debugging only

    inFile.seekg(4, ios::beg);
    inFile.read( (char*) &myChunkSize, 4 ); // read the ChunkSize

    inFile.seekg(16, ios::beg);
    inFile.read( (char*) &mySubChunk1Size, 4 ); // read the SubChunk1Size

    inFile.seekg(20, ios::beg);
    inFile.read( (char*) &myFormat, sizeof(short) ); // read the file format.  This should be 1 for PCM

    //inFile.seekg(22, ios::beg);
    inFile.read( (char*) &myChannels, sizeof(short) ); // read the # of channels (1 or 2)

    //inFile.seekg(24, ios::beg);
    inFile.read( (char*) &mySampleRate, sizeof(int) ); // read the samplerate

    //inFile.seekg(28, ios::beg);
    inFile.read( (char*) &myByteRate, sizeof(int) ); // read the byterate

    //inFile.seekg(32, ios::beg);
    inFile.read( (char*) &myBlockAlign, sizeof(short) ); // read the blockalign

    //inFile.seekg(34, ios::beg);
    inFile.read( (char*) &myBitsPerSample, sizeof(short) ); // read the bitspersample

    inFile.seekg(40, ios::beg);
    inFile.read( (char*) &myDataSize, sizeof(int) ); // read the size of the data


    // read the data chunk
    myData = new char[myDataSize];
    inFile.seekg(44, ios::beg);
    inFile.read(myData, myDataSize);

    inFile.close(); // close the input file

    my_signal = NULL;

    if ( myBitsPerSample == 8 )
    {
        mySignalSize = myDataSize;
        my_signal = new short[mySignalSize];
        for ( int i = 0; i < myDataSize; i++ )
            my_signal[i] = (short)( (unsigned char) myData[i] );

    }
    else if ( myBitsPerSample == 16 ){
        mySignalSize = myDataSize / 2;
        my_signal = new short[mySignalSize];
        short val;
        for ( int i = 0; i < myDataSize; i+=2 )
        {
            val = (short)( (unsigned char) myData[i] );
            val += (short)( (unsigned char) myData[i+1] ) * 256;
            my_signal[i/2] = val;
        }
    }
}

CWav.h:

#ifndef CWavH
#define CWavH

class CWav
{
private:
    char*   myData;
public:
    int     myChunkSize;
    int     mySubChunk1Size;
    short   myFormat;
    short   myChannels;
    int     mySampleRate;
    int     myByteRate;
    short   myBlockAlign;
    short   myBitsPerSample;
    int     myDataSize;

    short *my_signal;
    int mySignalSize;

public:

    void readInput(char *filename);

};

#endif

然后我有2个音频文件。 poolIR.wav AND test.wav

1 个答案:

答案 0 :(得分:1)

C ++不是脚本语言,你必须先编译它。

要使用gcc编译代码,请尝试以下操作 (假设所有文件都在同一目录中):

g++ convolve.cpp CWav.cpp -o convolve.exe

这应该生成一个名为 convolve.exe 的可执行文件。

-o标志指定输出文件名( convolve.exe )。 有关详细信息,请参阅gcc documentation