轉載:WAV header

轉自:http://www.cnblogs.com/CoderTian/p/6657844.htmlhtml

WAV爲微軟公司(Microsoft)開發的一種聲音文件格式,它符合RIFF(Resource Interchange File Format)文件規範,用於保存Windows平臺的音頻信息資源,被Windows平臺及其應用程序所普遍支持。WAVE文件一般只是一個具備單個「WAVE」塊的RIFF文件,該塊由兩個子塊(」fmt」子數據塊和」data」子數據塊),它的格式以下圖所示oop

該格式的實質就是在PCM文件的前面加了一個文件頭,每一個字段的的含義爲ui

typedef struct{
char ChunkID[4];//內容爲"RIFF"
unsigned long ChunkSize;//存儲文件的字節數(不包含ChunkID和ChunkSize這8個字節)
char Format[4];//內容爲"WAVE"
}WAVE_HEADER;
typedef struct{
char Subchunk1ID[4];//內容爲"fmt"
unsigned long Subchunk1Size;//存儲該子塊的字節數(不含前面的Subchunk1ID和Subchunk1Size這8個字節)
unsigned short AudioFormat;//存儲音頻文件的編碼格式,例如若爲PCM則其存儲值爲1,若爲其餘非PCM格式的則有必定的壓縮。
unsigned short NumChannels;//通道數,單通道(Mono)值爲1,雙通道(Stereo)值爲2,等等
unsigned long SampleRate;//採樣率,如8k,44.1k等
unsigned long ByteRate;//每秒存儲的bit數,其值=SampleRate * NumChannels * BitsPerSample/8
unsigned short BlockAlign;//塊對齊大小,其值=NumChannels * BitsPerSample/8
unsigned short BitsPerSample;//每一個採樣點的bit數,通常爲8,16,32等。
}WAVE_FMT;
typedef struct{
char Subchunk2ID[4];//內容爲「data」
unsigned long Subchunk2Size;//內容爲接下來的正式的數據部分的字節數,其值=NumSamples * NumChannels * BitsPerSample/8
}WAVE_DATA;編碼

 

好比下面的例子spa

這裏是一個WAVE文件的開頭72字節,字節顯示爲十六進制數字: 
52 49 46 46 24 08 00 00 57 41 56 45 66 6d 74 20 10 00 00 00 01 00 02 00 
22 56 00 00 88 58 01 00 04 00 10 00 64 61 74 61 00 08 00 00 00 00 00 00 
24 17 1e f3 3c 13 3c 14 16 f9 18 f9 34 e7 23 a6 3c f2 24 f2 11 ce 1a 0d 
字段解析:code

pcm 加上WAV header的代碼實現爲orm

int simplest_pcm16le_to_wave(const char *pcmpath,int channels,int sample_rate,const char *wavepath)
{
typedef struct WAVE_HEADER{
  char fccID[4];
  unsigned long dwSize;
  char fccType[4];
}WAVE_HEADER;
typedef struct WAVE_FMT{
  char fccID[4];
  unsigned long dwSize;
  unsigned short wFormatTag;
  unsigned short wChannels;
  unsigned long dwSamplesPerSec;
  unsigned long dwAvgBytesPerSec;
  unsigned short wBlockAlign;
  unsigned short uiBitsPerSample;
}WAVE_FMT;
typedef struct WAVE_DATA{
  char fccID[4];
  unsigned long dwSize;
}WAVE_DATA;
  if(channels==0||sample_rate==0){
    channels = 2;
    sample_rate = 44100;
  }
  int bits = 16;
  WAVE_HEADER pcmHEADER;
  WAVE_FMT pcmFMT;
  WAVE_DATA pcmDATA;

  unsigned short m_pcmData;
  FILE *fp,*fpout;
  fp=fopen(pcmpath, "rb");
  if(fp == NULL) {
    printf("open pcm file error\n");
    return -1;
  }
  fpout=fopen(wavepath, "wb+");
  if(fpout == NULL) {
    printf("create wav file error\n");
    return -1;
  }
  //WAVE_HEADER
  memcpy(pcmHEADER.fccID,"RIFF",strlen("RIFF"));
  memcpy(pcmHEADER.fccType,"WAVE",strlen("WAVE"));
  fseek(fpout,sizeof(WAVE_HEADER),1);
  //WAVE_FMT
  pcmFMT.dwSamplesPerSec=sample_rate;
  pcmFMT.dwAvgBytesPerSec=pcmFMT.dwSamplesPerSec*sizeof(m_pcmData);
  pcmFMT.uiBitsPerSample=bits;
  memcpy(pcmFMT.fccID,"fmt ",strlen("fmt "));
  pcmFMT.dwSize=16;
  pcmFMT.wBlockAlign=2;
  pcmFMT.wChannels=channels;
  pcmFMT.wFormatTag=1;

  fwrite(&pcmFMT,sizeof(WAVE_FMT),1,fpout);
  //WAVE_DATA;
  memcpy(pcmDATA.fccID,"data",strlen("data"));
  pcmDATA.dwSize=0;
  fseek(fpout,sizeof(WAVE_DATA),SEEK_CUR);
  fread(&m_pcmData,sizeof(unsigned short),1,fp);
  while(!feof(fp)){
    pcmDATA.dwSize+=2;
    fwrite(&m_pcmData,sizeof(unsigned short),1,fpout);
    fread(&m_pcmData,sizeof(unsigned short),1,fp);
  }
  pcmHEADER.dwSize=44+pcmDATA.dwSize;
  rewind(fpout);
  fwrite(&pcmHEADER,sizeof(WAVE_HEADER),1,fpout);
  fseek(fpout,sizeof(WAVE_FMT),SEEK_CUR);
  fwrite(&pcmDATA,sizeof(WAVE_DATA),1,fpout);

  fclose(fp);
  fclose(fpout);
  return 0;
}htm

 

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<pthread.h>
typedef struct{
char chunkId[4];//"RIFF"
unsigned long chunkSize;
char format[4];//"WAVE"
}WAVE_RIFF;
typedef struct{
char chunkId[4];//"fmt"
unsigned long chunkSize;
unsigned short audioFormat;
unsigned short chNum;
unsigned long sampleRate;
unsigned long byteRate;//SampleRate * NumChannels * BitsPerSample/8
unsigned short blockAlign;//NumChannels * BitsPerSample/8
unsigned short bitsPerSample;//8,16,32
}WAVE_FMT;
typedef struct{
char chunkId[4];//"data"
unsigned long chunkSize;//NumSamples * NumChannels * BitsPerSample/8
}WAVE_DATA;
typedef struct
{
    char fileName[256];
    FILE *fp;
    long pos;
    unsigned long totalSampleNum;
    WAVE_RIFF riffChunk;
    WAVE_FMT fmtChunk;
    WAVE_DATA dataChunk;
}WAVE_INFO;

#define READ_SAMPLES 256
#define PP_SAMPLES 64
typedef struct
{
    unsigned short chNum;
    unsigned short bankNum;
    unsigned long samplesPerBank;
    unsigned short bytesPerSample;
    unsigned short bankRp;
    unsigned short bankWp;
    unsigned char ***pData;
    unsigned char fgEos;
}PP_BUF_T;

PP_BUF_T gPpBuf;
unsigned char fgEnd = 0;
void printWaveHeader(WAVE_INFO *pWaveInfo)
{
    printf("fileName:%s\n", pWaveInfo->fileName);
    printf("riff chunk:\n");
    printf("chunkId:%c%c%c%c\n", pWaveInfo->riffChunk.chunkId[0], pWaveInfo->riffChunk.chunkId[1], pWaveInfo->riffChunk.chunkId[2], pWaveInfo->riffChunk.chunkId[3]);
    printf("chunkSize:%ld\n", pWaveInfo->riffChunk.chunkSize);
    printf("format:%c%c%c%c\n", pWaveInfo->riffChunk.format[0], pWaveInfo->riffChunk.format[1], pWaveInfo->riffChunk.format[2], pWaveInfo->riffChunk.format[3]);
    printf("fmt chunk:\n");
    printf("chunkId:%c%c%c\n", pWaveInfo->fmtChunk.chunkId[0], pWaveInfo->fmtChunk.chunkId[1], pWaveInfo->fmtChunk.chunkId[2]);
    printf("chunkSize:%ld\n", pWaveInfo->fmtChunk.chunkSize);
    printf("audioFormat:%d\n", pWaveInfo->fmtChunk.audioFormat);
    printf("chNum:%d\n", pWaveInfo->fmtChunk.chNum);
    printf("sampleRate:%ld\n", pWaveInfo->fmtChunk.sampleRate);
    printf("byteRate:%ld\n", pWaveInfo->fmtChunk.byteRate);
    printf("blockAlign:%d\n", pWaveInfo->fmtChunk.blockAlign);
    printf("bitsPerSample:%d\n", pWaveInfo->fmtChunk.bitsPerSample);
    printf("data chunk:\n");
    printf("chunkId:%c%c%c%c\n", pWaveInfo->dataChunk.chunkId[0], pWaveInfo->dataChunk.chunkId[1], pWaveInfo->dataChunk.chunkId[2], pWaveInfo->dataChunk.chunkId[3]);
    printf("chunkSize:%ld\n", pWaveInfo->dataChunk.chunkSize);
    
}
void initWaveInfo(WAVE_INFO *pWaveInfo, unsigned short chNum, unsigned long sampleRate, unsigned short bitsPerSample)
{
    //strncpy(pWaveInfo->riffChunk.chunkId, "RIFF", 4);
    pWaveInfo->riffChunk.chunkId[0] = 'R';
    pWaveInfo->riffChunk.chunkId[1] = 'I';
    pWaveInfo->riffChunk.chunkId[2] = 'F';
    pWaveInfo->riffChunk.chunkId[3] = 'F';
    pWaveInfo->riffChunk.chunkSize = 0;
    //strncpy(pWaveInfo->riffChunk.format, "WAVE", 4);
    pWaveInfo->riffChunk.format[0] = 'W';
    pWaveInfo->riffChunk.format[1] = 'A';
    pWaveInfo->riffChunk.format[2] = 'V';
    pWaveInfo->riffChunk.format[3] = 'E';
    //strncpy(pWaveInfo->fmtChunk.chunkId, "fmt", 3);
    pWaveInfo->fmtChunk.chunkId[0] = 'f';
    pWaveInfo->fmtChunk.chunkId[1] = 'm';
    pWaveInfo->fmtChunk.chunkId[2] = 't';
    pWaveInfo->fmtChunk.chunkId[3] = ' ';
    pWaveInfo->fmtChunk.chunkSize = sizeof(WAVE_FMT) - 8;
    pWaveInfo->fmtChunk.audioFormat = 1;
    pWaveInfo->fmtChunk.chNum = chNum;
    pWaveInfo->fmtChunk.sampleRate = sampleRate;
    pWaveInfo->fmtChunk.byteRate = sampleRate * chNum * bitsPerSample / 8;
    pWaveInfo->fmtChunk.blockAlign = chNum * bitsPerSample / 8;
    pWaveInfo->fmtChunk.bitsPerSample = bitsPerSample;
    //strncpy(pWaveInfo->dataChunk.chunkId, "data", 4);
    pWaveInfo->dataChunk.chunkId[0] = 'd';
    pWaveInfo->dataChunk.chunkId[1] = 'a';
    pWaveInfo->dataChunk.chunkId[2] = 't';
    pWaveInfo->dataChunk.chunkId[3] = 'a';
    
    pWaveInfo->dataChunk.chunkSize = 0;
    pWaveInfo->totalSampleNum = 0;
    ///printWaveHeader(pWaveInfo);
}

void rwRiffChunk(WAVE_INFO *pWaveInfo, unsigned char fgRead)
{
    if (fgRead)
    {
        fread((char *)&pWaveInfo->riffChunk.chunkId, 4, 1, pWaveInfo->fp);
        fread((char *)&pWaveInfo->riffChunk.chunkSize, 4, 1, pWaveInfo->fp);
        fread((char *)&pWaveInfo->riffChunk.format, 4, 1, pWaveInfo->fp);
    }
    else
    {
        fwrite((char *)&pWaveInfo->riffChunk.chunkId, 4, 1, pWaveInfo->fp);
        fwrite((char *)&pWaveInfo->riffChunk.chunkSize, 4, 1, pWaveInfo->fp);
        fwrite((char *)&pWaveInfo->riffChunk.format, 4, 1, pWaveInfo->fp);
    }
}
void rwFmtChunk(WAVE_INFO *pWaveInfo, unsigned char fgRead)
{
    if (fgRead)
    {
        fread((char *)&pWaveInfo->fmtChunk.chunkId, 4, 1, pWaveInfo->fp);
        fread((char *)&pWaveInfo->fmtChunk.chunkSize, 4, 1, pWaveInfo->fp);
        fread((char *)&pWaveInfo->fmtChunk.audioFormat, 2, 1, pWaveInfo->fp);
        fread((char *)&pWaveInfo->fmtChunk.chNum, 2, 1, pWaveInfo->fp);
        fread((char *)&pWaveInfo->fmtChunk.sampleRate, 4, 1, pWaveInfo->fp);
        fread((char *)&pWaveInfo->fmtChunk.byteRate, 4, 1, pWaveInfo->fp);
        fread((char *)&pWaveInfo->fmtChunk.blockAlign, 2, 1, pWaveInfo->fp);
        fread((char *)&pWaveInfo->fmtChunk.bitsPerSample, 2, 1, pWaveInfo->fp);
    }
    else
    {
        fwrite((char *)&pWaveInfo->fmtChunk.chunkId, 4, 1, pWaveInfo->fp);
        fwrite((char *)&pWaveInfo->fmtChunk.chunkSize, 4, 1, pWaveInfo->fp);
        fwrite((char *)&pWaveInfo->fmtChunk.audioFormat, 2, 1, pWaveInfo->fp);
        fwrite((char *)&pWaveInfo->fmtChunk.chNum, 2, 1, pWaveInfo->fp);
        fwrite((char *)&pWaveInfo->fmtChunk.sampleRate, 4, 1, pWaveInfo->fp);
        fwrite((char *)&pWaveInfo->fmtChunk.byteRate, 4, 1, pWaveInfo->fp);
        fwrite((char *)&pWaveInfo->fmtChunk.blockAlign, 2, 1, pWaveInfo->fp);
        fwrite((char *)&pWaveInfo->fmtChunk.bitsPerSample, 2, 1, pWaveInfo->fp);
        
    }
}
void rwDataChunk(WAVE_INFO *pWaveInfo, unsigned char fgRead)
{
    if (fgRead)
    {
        fread((char *)&pWaveInfo->dataChunk.chunkId, 4, 1, pWaveInfo->fp);
        fread((char *)&pWaveInfo->dataChunk.chunkSize, 4, 1, pWaveInfo->fp);
    }
    else
    {
        fwrite((char *)&pWaveInfo->dataChunk.chunkId, 4, 1, pWaveInfo->fp);
        fwrite((char *)&pWaveInfo->dataChunk.chunkSize, 4, 1, pWaveInfo->fp);
    }
}

void readWaveHeader(char *fileName, WAVE_INFO *pWaveInfo)
{
    size_t retSize;
    strncpy(pWaveInfo->fileName, fileName, strlen(fileName));
    pWaveInfo->fp = fopen(fileName, "rb");
    if (pWaveInfo->fp == NULL)
    {
        printf("fopen fail, errno:%d\n", errno);
        return;
    }
    #if 0
    retSize = fread((char *)&pWaveInfo->riffChunk, sizeof(WAVE_RIFF), 1, pWaveInfo->fp);
    retSize = fread((char *)&pWaveInfo->fmtChunk, sizeof(WAVE_FMT), 1, pWaveInfo->fp);
    retSize = fread((char *)&pWaveInfo->dataChunk, sizeof(WAVE_DATA), 1, pWaveInfo->fp);
    #endif
    rwRiffChunk(pWaveInfo, 1);
    rwFmtChunk(pWaveInfo, 1);
    rwDataChunk(pWaveInfo, 1);
    pWaveInfo->pos = ftell(pWaveInfo->fp);
    pWaveInfo->totalSampleNum = pWaveInfo->dataChunk.chunkSize / (pWaveInfo->fmtChunk.bitsPerSample / 8);
    fclose(pWaveInfo->fp);
    printWaveHeader(pWaveInfo);
}

void initPpBuf(unsigned short chNum, unsigned short bankNum, unsigned long samplesPerBank, unsigned short bytesPerSample)
{
    unsigned short chIdx, bankIdx;
    gPpBuf.chNum = chNum;    
    gPpBuf.bankNum = bankNum;    
    gPpBuf.samplesPerBank = samplesPerBank;
    gPpBuf.bytesPerSample = bytesPerSample;

    gPpBuf.bankRp = gPpBuf.bankWp = 0;
    gPpBuf.fgEos = 0;
    gPpBuf.pData = (unsigned char ***)malloc(chNum * sizeof(unsigned char **));
    for (chIdx = 0; chIdx < chNum; chIdx++)
    {
        gPpBuf.pData[chIdx] = (unsigned char **)malloc(bankNum * sizeof(unsigned char *));
        for (bankIdx =0; bankIdx < bankNum; bankIdx++)
        {
            gPpBuf.pData[chIdx][bankIdx] = (unsigned char *) malloc(samplesPerBank * bytesPerSample * sizeof(unsigned char));
        }
    }
}

int sendData(unsigned char *writeBuffer, unsigned short chNum)
{
    unsigned short sampleIdx, chIdx, byteIdx;
    printf("sendData, wp:%d, rp:%d\n", gPpBuf.bankWp, gPpBuf.bankRp);
    if ((gPpBuf.bankWp + 1 ) % gPpBuf.bankNum == gPpBuf.bankRp)
    {
        //full
        return 1;
    }
    else
    {
        for (sampleIdx = 0; sampleIdx < PP_SAMPLES; sampleIdx++)
        {
            for (chIdx =0; chIdx < chNum; chIdx++)
            {
                for (byteIdx = 0; byteIdx < gPpBuf.bytesPerSample; byteIdx++)
                {
               gPpBuf.pData[chIdx][gPpBuf.bankWp][sampleIdx * gPpBuf.bytesPerSample + byteIdx] = writeBuffer[(chIdx + sampleIdx * chNum) * gPpBuf.bytesPerSample + byteIdx];  
          }
            }
        }
        gPpBuf.bankWp = (gPpBuf.bankWp + 1) % gPpBuf.bankNum;
    }
    return 0;
}

int recvData(unsigned char **readBuffer)
{
    unsigned short chIdx;
    printf("recvData, wp:%d, rp:%d\n", gPpBuf.bankWp, gPpBuf.bankRp);
    if (gPpBuf.bankWp == gPpBuf.bankRp)
    {
        //empty
        return 1;
    }
    else
    {
        for (chIdx = 0; chIdx < gPpBuf.chNum; chIdx++)
        {
            memcpy(&readBuffer[chIdx][0], &gPpBuf.pData[chIdx][gPpBuf.bankRp][0], PP_SAMPLES * gPpBuf.bytesPerSample * sizeof(unsigned char));
        }
        gPpBuf.bankRp = (gPpBuf.bankRp + 1) % gPpBuf.bankNum;
    }
    return 0;
}
void *readThread(void *arg)
{
    char *fileName = (char *)arg;
    size_t retSize;
    WAVE_INFO waveInfo;
    memset(&waveInfo, 0, sizeof(WAVE_INFO));
    unsigned long bytesPerLoop;
    unsigned short loopIdx, loop;
    unsigned long readCount = 0;
    readWaveHeader(fileName, &waveInfo);
    unsigned long readSize = READ_SAMPLES * waveInfo.fmtChunk.chNum * waveInfo.fmtChunk.bitsPerSample / 8;
    printf("readSize:%ld\n", readSize);
    unsigned char *readBuffer = (unsigned char *)malloc(readSize * sizeof(unsigned char));
    waveInfo.fp = fopen(fileName, "rb");
    fseek(waveInfo.fp,  waveInfo.pos, SEEK_SET);
    while (1)
    {
        retSize = fread(readBuffer, readSize, 1, waveInfo.fp);
        if (retSize <= 0)
        {
             printf("fread fail,retSize:%d, %s, eof:%d, readCount:%ld\n", (int) retSize, strerror(errno), feof(waveInfo.fp), readCount);
             gPpBuf.fgEos = 1;
             break;
        }
        else
        {
             bytesPerLoop = PP_SAMPLES *waveInfo.fmtChunk.chNum * waveInfo.fmtChunk.bitsPerSample / 8;
             loop = readSize / bytesPerLoop;
             loopIdx = 0;
             while (loopIdx < loop)
             {
                 if (0 != sendData(readBuffer + loopIdx * bytesPerLoop, waveInfo.fmtChunk.chNum))
                 {
                     usleep(1000);
                 }
                 else
                 {
                     loopIdx++;
                 }
             }
             readCount++; 
        }
    }
    return NULL;
}
void pp()
{
}

void saveOneChInWave(unsigned char *pData, unsigned long size, WAVE_INFO *pWaveInfo)
{
   size_t retSize = 0;
   if (pWaveInfo->fp == NULL)
   {
       pWaveInfo->fp = fopen(pWaveInfo->fileName, "wb");
       #if 0
       retSize = fwrite((char *)&pWaveInfo->riffChunk, sizeof(WAVE_RIFF), 1, pWaveInfo->fp);
       retSize = fwrite((char *)&pWaveInfo->fmtChunk, sizeof(WAVE_FMT), 1, pWaveInfo->fp);
        retSize = fwrite((char *)&pWaveInfo->dataChunk, sizeof(WAVE_DATA), 1, pWaveInfo->fp);
        #endif
        rwRiffChunk(pWaveInfo, 0);
        rwFmtChunk(pWaveInfo, 0);
        rwDataChunk(pWaveInfo, 0);   
    } 
    retSize = fwrite(pData, size, 1, pWaveInfo->fp);
    pWaveInfo->totalSampleNum += (size / pWaveInfo->fmtChunk.chNum / (pWaveInfo->fmtChunk.bitsPerSample / 8));
    pWaveInfo->pos = ftell(pWaveInfo->fp);
}

void updateWaveHeader(WAVE_INFO *pWaveInfo)
{
    size_t retSize;
    pWaveInfo->riffChunk.chunkSize = pWaveInfo->pos - 8;
    pWaveInfo->dataChunk.chunkSize = pWaveInfo->totalSampleNum * pWaveInfo->fmtChunk.chNum * pWaveInfo->fmtChunk.bitsPerSample / 8;
    fseek(pWaveInfo->fp,  0, SEEK_SET);
    #if 0
    retSize = fwrite((char *)&pWaveInfo->riffChunk, sizeof(WAVE_RIFF), 1, pWaveInfo->fp);
    retSize = fwrite((char *)&pWaveInfo->fmtChunk, sizeof(WAVE_FMT), 1, pWaveInfo->fp);
    retSize = fwrite((char *)&pWaveInfo->dataChunk, sizeof(WAVE_DATA), 1, pWaveInfo->fp);
    #endif    
    rwRiffChunk(pWaveInfo, 0);
    rwFmtChunk(pWaveInfo, 0);
    rwDataChunk(pWaveInfo, 0);   
    fclose(pWaveInfo->fp);
    
    printWaveHeader(pWaveInfo);
}
void *ppThread(void *arg)
{
    char *fileName = (char *)arg;
    WAVE_INFO waveInfo;
    memset(&waveInfo, 0, sizeof(waveInfo));
    strncpy(waveInfo.fileName, fileName, strlen(fileName));
    printf("out file:%s\n", waveInfo.fileName);
    waveInfo.fp = NULL;
    initWaveInfo(&waveInfo, 1, 48000, 16);
    unsigned char **readBuffer = (unsigned char **)malloc(gPpBuf.chNum * sizeof(unsigned char *));
    unsigned short chIdx;
    for(chIdx = 0; chIdx < gPpBuf.chNum; chIdx++)
    {
        readBuffer[chIdx] = (unsigned char *)malloc(PP_SAMPLES * gPpBuf.bytesPerSample * sizeof(unsigned char));
    }
    while (1)
    {
        if (0 != recvData(readBuffer))
        {
            if (gPpBuf.fgEos)
                break;
            usleep(1000);
        }
        else
        {
            saveOneChInWave(readBuffer[0], PP_SAMPLES * gPpBuf.bytesPerSample, &waveInfo);
            pp();
        }
    }
    updateWaveHeader(&waveInfo);
    fgEnd = 1;
}

int main(int argc, char **argv)
{
#if 0
    WAVE_INFO inputWaveInfo, outputWaveInfo;
    readWaveHeader(argv[1], &inputWaveInfo);
    //initWaveInfo(&outputWaveInfo, 2, 48000, 16);
#endif
    
#if 1
    pthread_t readThreadId, ppThreadId;
    initPpBuf(6, 3, PP_SAMPLES, 2);
    pthread_create(&readThreadId, NULL, readThread, argv[1]);
    pthread_create(&ppThreadId, NULL, ppThread, argv[2]);
    while(!fgEnd)
    {
        sleep(1);
    }
#endif
    return 0;
}
相關文章
相關標籤/搜索