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

📄 pwavfile.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 3 页
字号:
    if (autoConverter == NULL) {
      PTRACE(1, "PWAVFile\tNo format converter for type " << (int)wavFmtChunk.format);
      return FALSE;
    }
  }

  return (TRUE);
}

// Update the WAV header according to the file length
BOOL PWAVFile::UpdateHeader()
{
  // Check file is still open
  if (!IsOpen()) {
    PTRACE(1,"WAV\tUpdateHeader: Not Open");
    return (FALSE);
  }

  // Check there is already a valid header
  if (!isValidWAV) {
    PTRACE(1,"WAV\tUpdateHeader: File not valid");
    return (FALSE);
  }

  // Find out the length of the audio data
  lenData = PFile::GetLength() - lenHeader;

  // rewrite the length in the RIFF chunk
  PInt32l riffChunkLen = (lenHeader - 8) + lenData; // size does not include first 8 bytes
  PFile::SetPosition(4);
  if (!WriteAndCheck(*this, &riffChunkLen, sizeof(riffChunkLen)))
    return FALSE;

  // rewrite the data length field in the data chunk
  PInt32l dataChunkLen;
  dataChunkLen = lenData;
  PFile::SetPosition(lenHeader - 4);
  if (!WriteAndCheck(*this, &dataChunkLen, sizeof(dataChunkLen)))
    return FALSE;

  header_needs_updating = FALSE;

  return TRUE;
}


//////////////////////////////////////////////////////////////////

BOOL PWAVFileFormat::Read(PWAVFile & file, void * buf, PINDEX & len)
{ 
  if (!file.RawRead(buf, len))
    return FALSE;

  len = file.GetLastReadCount();
  return TRUE;
}

BOOL PWAVFileFormat::Write(PWAVFile & file, const void * buf, PINDEX & len)
{ 
  if (!file.RawWrite(buf, len))
    return FALSE;

  len = file.GetLastWriteCount();
  return TRUE;
}

//////////////////////////////////////////////////////////////////

class PWAVFileFormatPCM : public PWAVFileFormat
{
  public:
    virtual ~PWAVFileFormatPCM() {}
    void CreateHeader(PWAV::FMTChunk & wavFmtChunk, PBYTEArray & extendedHeader);
    PString GetDescription() const;
    unsigned GetFormat() const;
    PString GetFormatString() const;

    BOOL Read(PWAVFile & file, void * buf, PINDEX & len);
    BOOL Write(PWAVFile & file, const void * buf, PINDEX & len);
};

PWAVFileFormatByIDFactory::Worker<PWAVFileFormatPCM> pcmIDWAVFormat(PWAVFile::fmt_PCM);
PWAVFileFormatByFormatFactory::Worker<PWAVFileFormatPCM> pcmFormatWAVFormat("PCM-16");

unsigned PWAVFileFormatPCM::GetFormat() const
{
  return PWAVFile::fmt_PCM;
}

PString PWAVFileFormatPCM::GetDescription() const
{
  return "PCM";
}

PString PWAVFileFormatPCM::GetFormatString() const
{
  return "PCM-16";
}

void PWAVFileFormatPCM::CreateHeader(PWAV::FMTChunk & wavFmtChunk, 
                                     PBYTEArray & /*extendedHeader*/)
{
  wavFmtChunk.hdr.len         = sizeof(wavFmtChunk) - sizeof(wavFmtChunk.hdr);  // no extended information
  wavFmtChunk.format          = PWAVFile::fmt_PCM;
  wavFmtChunk.numChannels     = 1;
  wavFmtChunk.sampleRate      = 8000;
  wavFmtChunk.bytesPerSample  = 2;
  wavFmtChunk.bitsPerSample   = 16;
  wavFmtChunk.bytesPerSec     = wavFmtChunk.sampleRate * wavFmtChunk.bytesPerSample;
}

BOOL PWAVFileFormatPCM::Read(PWAVFile & file, void * buf, PINDEX & len)
{
  if (!file.FileRead(buf, len))
    return FALSE;

  len = file.GetLastReadCount();

  // WAV files are little-endian. So swap the bytes if this is
  // a big endian machine and we have 16 bit samples
  // Note: swab only works on even length buffers.
  if (file.wavFmtChunk.bitsPerSample == 16) {
    SWAB(buf, buf, len);
  }

  return TRUE;
}

BOOL PWAVFileFormatPCM::Write(PWAVFile & file, const void * buf, PINDEX & len)
{
  // WAV files are little-endian. So swap the bytes if this is
  // a big endian machine and we have 16 bit samples
  // Note: swab only works on even length buffers.
  if (file.wavFmtChunk.bitsPerSample == 16) {
    SWAB(buf, (void *)buf, len);
  }

  if (!file.FileWrite(buf, len))
    return FALSE;

  len = file.GetLastWriteCount();
  return TRUE;
}

//////////////////////////////////////////////////////////////////

#ifdef __GNUC__
#define P_PACKED    __attribute__ ((packed));
#else
#define P_PACKED
#pragma pack(1)
#endif

struct G7231ExtendedInfo {
  PInt16l data1      P_PACKED;      // 1
  PInt16l data2      P_PACKED;      // 480
};

struct G7231FACTChunk {
  PWAV::ChunkHeader hdr;
  PInt32l data1      P_PACKED;      // 0   Should be number of samples.
};

#ifdef __GNUC__
#undef P_PACKED
#else
#pragma pack()
#endif


class PWAVFileFormatG7231 : public PWAVFileFormat
{
  public:
    PWAVFileFormatG7231(unsigned short _g7231)
      : g7231(_g7231) { }

    virtual ~PWAVFileFormatG7231() {}

    void CreateHeader(PWAV::FMTChunk & wavFmtChunk, PBYTEArray & extendedHeader);
    BOOL WriteExtraChunks(PWAVFile & file);

    PString GetFormatString() const
    { return "G.723.1"; }   // must match string in mediafmt.h

    void OnStart();
    BOOL Read(PWAVFile & file, void * buf, PINDEX & len);
    BOOL Write(PWAVFile & file, const void * buf, PINDEX & len);

  protected:
    unsigned short g7231;
    BYTE cacheBuffer[24];
    PINDEX cacheLen;
    PINDEX cachePos;
};

void PWAVFileFormatG7231::CreateHeader(PWAV::FMTChunk & wavFmtChunk, PBYTEArray & extendedHeader)
{
  wavFmtChunk.hdr.len         = sizeof(wavFmtChunk) - sizeof(wavFmtChunk.hdr) + sizeof(sizeof(G7231ExtendedInfo));
  wavFmtChunk.format          = g7231;
  wavFmtChunk.numChannels     = 1;
  wavFmtChunk.sampleRate      = 8000;
  wavFmtChunk.bytesPerSample  = 24;
  wavFmtChunk.bitsPerSample   = 0;
  wavFmtChunk.bytesPerSec     = 800;

  extendedHeader.SetSize(sizeof(G7231ExtendedInfo));
  G7231ExtendedInfo * g7231Info = (G7231ExtendedInfo *)extendedHeader.GetPointer(sizeof(G7231ExtendedInfo));

  g7231Info->data1 = 1;
  g7231Info->data2 = 480;
}

BOOL PWAVFileFormatG7231::WriteExtraChunks(PWAVFile & file)
{
  // write the fact chunk
  G7231FACTChunk factChunk;
  memcpy(factChunk.hdr.tag, "FACT", 4);
  factChunk.hdr.len = sizeof(factChunk) - sizeof(factChunk.hdr);
  factChunk.data1 = 0;
  return file.FileWrite(&factChunk, sizeof(factChunk));
}

static PINDEX G7231FrameSizes[4] = { 24, 20, 4, 1 };

void PWAVFileFormatG7231::OnStart()
{
  cacheLen = cachePos = 0;
}

BOOL PWAVFileFormatG7231::Read(PWAVFile & file, void * origData, PINDEX & origLen)
{
  // Note that Microsoft && VivoActive G.2723.1 codec cannot do SID frames, so
  // we must parse the data and remove SID frames
  // also note that frames are always written as 24 byte frames, so each frame must be unpadded

  PINDEX bytesRead = 0;
  while (bytesRead < origLen) {

    // keep reading until we find a 20 or 24 byte frame
    while (cachePos == cacheLen) {
      if (!file.FileRead(cacheBuffer, 24))
        return FALSE;

      // calculate actual length of frame
      PINDEX frameLen = G7231FrameSizes[cacheBuffer[0] & 3];
      if (frameLen == 20 || frameLen == 24) {
        cacheLen = frameLen;
        cachePos = 0;
      }
    }

    // copy data to requested buffer
    PINDEX copyLen = PMIN(origLen-bytesRead, cacheLen-cachePos);
    memcpy(origData, cacheBuffer+cachePos, copyLen);
    origData = copyLen + (char *)origData;
    cachePos += copyLen;
    bytesRead += copyLen;
  }

  origLen = bytesRead;

  return TRUE;
}

BOOL PWAVFileFormatG7231::Write(PWAVFile & file, const void * origData, PINDEX & len)
{
  // Note that Microsoft && VivoActive G.2723.1 codec cannot do SID frames, so
  // we must parse the data and remove SID frames
  // also note that frames are always written as 24 byte frames, so each frame must be padded
  PINDEX written = 0;

  BYTE frameBuffer[24];
  while (len > 0) {

    // calculate actual length of frame
    PINDEX frameLen = G7231FrameSizes[(*(char *)origData) & 3];
    if (len < frameLen)
      return FALSE;

    // we can write 24 byte frame straight out, 
    // 20 byte frames need to be reblocked
    // we ignore any other frames

    const void * buf = NULL;
    switch (frameLen) {
      case 24:
        buf = origData;
        break;
      case 20:
        memcpy(frameBuffer, origData, 20);
        buf = frameBuffer;
        break;
      default:
        break;
    }

    if (buf != NULL && !file.FileWrite(buf, 24))
      return FALSE;
    else
      written += 24;

    origData = (char *)origData + frameLen;
    len -= frameLen;
  }

  len = written;

  return TRUE;
}

class PWAVFileFormatG7231_vivo : public PWAVFileFormatG7231
{
  public:
    PWAVFileFormatG7231_vivo()
      : PWAVFileFormatG7231(PWAVFile::fmt_VivoG7231) { }
    virtual ~PWAVFileFormatG7231_vivo() {}
    unsigned GetFormat() const
    { return PWAVFile::fmt_VivoG7231; }
    PString GetDescription() const
    { return GetFormatString() & "Vivo"; }
};

PWAVFileFormatByIDFactory::Worker<PWAVFileFormatG7231_vivo> g7231VivoWAVFormat(PWAVFile::fmt_VivoG7231);
PWAVFileFormatByFormatFactory::Worker<PWAVFileFormatG7231_vivo> g7231FormatWAVFormat("G.723.1");

class PWAVFileFormatG7231_ms : public PWAVFileFormatG7231
{
  public:
    PWAVFileFormatG7231_ms()
      : PWAVFileFormatG7231(PWAVFile::fmt_MSG7231) { }
    virtual ~PWAVFileFormatG7231_ms() {}
    unsigned GetFormat() const
    { return PWAVFile::fmt_MSG7231; }
    PString GetDescription() const
    { return GetFormatString() & "MS"; }
};

PWAVFileFormatByIDFactory::Worker<PWAVFileFormatG7231_ms> g7231MSWAVFormat(PWAVFile::fmt_MSG7231);

//////////////////////////////////////////////////////////////////

class PWAVFileConverterPCM : public PWAVFileConverter
{
  public:
    virtual ~PWAVFileConverterPCM() {}
    unsigned GetFormat    (const PWAVFile & file) const;
    off_t GetPosition     (const PWAVFile & file) const;
    BOOL SetPosition      (PWAVFile & file, off_t pos, PFile::FilePositionOrigin origin);
    unsigned GetSampleSize(const PWAVFile & file) const;
    off_t GetDataLength   (PWAVFile & file);
    BOOL Read             (PWAVFile & file, void * buf, PINDEX len);
    BOOL Write            (PWAVFile & file, const void * buf, PINDEX len);
};

unsigned PWAVFileConverterPCM::GetFormat(const PWAVFile &) const
{
  return PWAVFile::fmt_PCM;
}

off_t PWAVFileConverterPCM::GetPosition(const PWAVFile & file) const
{
  off_t pos = file.RawGetPosition();
  return pos * 2;
}

BOOL PWAVFileConverterPCM::SetPosition(PWAVFile & file, off_t pos, PFile::FilePositionOrigin origin)
{
  pos /= 2;
  return file.SetPosition(pos, origin);
}

unsigned PWAVFileConverterPCM::GetSampleSize(const PWAVFile &) const
{
  return 16;
}

off_t PWAVFileConverterPCM::GetDataLength(PWAVFile & file)
{
  return file.RawGetDataLength() * 2;
}

BOOL PWAVFileConverterPCM::Read(PWAVFile & file, void * buf, PINDEX len)
{
  if (file.wavFmtChunk.bitsPerSample == 16)
    return file.PWAVFile::RawRead(buf, len);

  if (file.wavFmtChunk.bitsPerSample != 8) {
    PTRACE(1, "PWAVFile\tAttempt to read autoconvert PCM data with unsupported number of bits per sample " << (int)file.wavFmtChunk.bitsPerSample);
    return FALSE;
  }

  // read the PCM data with 8 bits per sample
  PINDEX samples = (len / 2);
  PBYTEArray pcm8;
  if (!file.PWAVFile::RawRead(pcm8.GetPointer(samples), samples))
    return FALSE;

  // convert to PCM-16
  PINDEX i;
  short * pcmPtr = (short *)buf;
  for (i = 0; i < samples; i++)
    *pcmPtr++ = (unsigned short)((pcm8[i] << 8) - 0x8000);

  // fake the lastReadCount
  file.SetLastReadCount(len);

  return TRUE;
}


BOOL PWAVFileConverterPCM::Write(PWAVFile & file, const void * buf, PINDEX len)
{
  if (file.wavFmtChunk.bitsPerSample == 16)
    return file.PWAVFile::RawWrite(buf, len);

  PTRACE(1, "PWAVFile\tAttempt to write autoconvert PCM data with unsupported number of bits per sample " << (int)file.wavFmtChunk.bitsPerSample);
  return FALSE;
}

PWAVFileConverterFactory::Worker<PWAVFileConverterPCM> pcmConverter(PWAVFile::fmt_PCM, true);

//////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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