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

📄 pwavfile.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 3 页
字号:
  }

  if (!PFile::IsOpen())
    return TRUE;

  if (header_needs_updating)
    UpdateHeader();

  if (formatHandler != NULL) 
    formatHandler->OnStop();

  delete formatHandler;
  formatHandler = NULL;
  if (origFmt != 0xffffffff)
    SelectFormat(origFmt);

  return PFile::Close();
}

void PWAVFile::SetAutoconvert()
{ 
  autoConvert = TRUE; 
}


// Performs necessary byte-order swapping on for big-endian platforms.
BOOL PWAVFile::Read(void * buf, PINDEX len)
{
  if (autoConverter != NULL)
    return autoConverter->Read(*this, buf, len);

  return RawRead(buf, len);
}

BOOL PWAVFile::RawRead(void * buf, PINDEX len)
{
  // Some wav files have extra data after the sound samples in a LIST chunk.
  // e.g. WAV files made in GoldWave have a copyright and a URL in this chunk.
  // We do not want to return this data by mistake.
  PINDEX readlen = len;
  off_t pos = PFile::GetPosition();
  if (pos >= (lenHeader+lenData))
    return FALSE;
  
  if ((pos + len) > (lenHeader+lenData))
    readlen = (lenHeader+lenData) - pos;

  if (formatHandler != NULL)
    return formatHandler->Read(*this, buf, readlen);

  return FileRead(buf, readlen);
}

BOOL PWAVFile::FileRead(void * buf, PINDEX len)
{
  return PFile::Read(buf, len);
}

// Performs necessary byte-order swapping on for big-endian platforms.
BOOL PWAVFile::Write(const void * buf, PINDEX len)
{
  // Needs to update header on close.
  header_needs_updating = TRUE;

  if (autoConverter != NULL)
    return autoConverter->Write(*this, buf, len);

  return RawWrite(buf, len);
}

BOOL PWAVFile::RawWrite(const void * buf, PINDEX len)
{
  // Needs to update header on close.
  header_needs_updating = TRUE;

  if (formatHandler != NULL)
    return formatHandler->Write(*this, buf, len);

  return FileWrite(buf, len);
}

BOOL PWAVFile::FileWrite(const void * buf, PINDEX len)
{
  return PFile::Write(buf, len);
}

// Both SetPosition() and GetPosition() are offset by lenHeader.
BOOL PWAVFile::SetPosition(off_t pos, FilePositionOrigin origin)
{
  if (autoConverter != NULL)
    return autoConverter->SetPosition(*this, pos, origin);

  return RawSetPosition(pos, origin);
}

BOOL PWAVFile::RawSetPosition(off_t pos, FilePositionOrigin origin)
{
  if (isValidWAV) {
    pos += lenHeader;
  }

  return PFile::SetPosition(pos, origin);
}


off_t PWAVFile::GetPosition() const
{
  if (autoConverter != NULL)
    return autoConverter->GetPosition(*this);

  return RawGetPosition();
}

off_t PWAVFile::RawGetPosition() const
{
  off_t pos = PFile::GetPosition();

  if (isValidWAV) {
    if (pos >= lenHeader) {
      pos -= lenHeader;
    }
    else {
      pos = 0;
    }
  }

  return (pos);
}


unsigned PWAVFile::GetFormat() const
{
  if (isValidWAV)
    return wavFmtChunk.format;
  else
    return 0;
}

PString PWAVFile::GetFormatAsString() const
{
  if (isValidWAV && formatHandler != NULL)
    return formatHandler->GetFormat();
  else
    return PString::Empty();
}

unsigned PWAVFile::GetChannels() const
{
  if (isValidWAV)
    return wavFmtChunk.numChannels;
  else
    return 0;
}

void PWAVFile::SetChannels(unsigned v) 
{
  wavFmtChunk.numChannels = (WORD)v;
  header_needs_updating = TRUE;
}

unsigned PWAVFile::GetSampleRate() const
{
  if (isValidWAV)
    return wavFmtChunk.sampleRate;
  else
    return 0;
}

void PWAVFile::SetSampleRate(unsigned v) 
{
  wavFmtChunk.sampleRate = (WORD)v;
  header_needs_updating = TRUE;
}

unsigned PWAVFile::GetSampleSize() const
{
  if (isValidWAV)
    return wavFmtChunk.bitsPerSample;
  else
    return 0;
}

void PWAVFile::SetSampleSize(unsigned v) 
{
  wavFmtChunk.bitsPerSample = (WORD)v;
  header_needs_updating = TRUE;
}

off_t PWAVFile::GetHeaderLength() const
{
  if (isValidWAV)
    return lenHeader;
  else
    return 0;
}


off_t PWAVFile::GetDataLength()
{
  if (autoConverter != NULL)
    return autoConverter->GetDataLength(*this);

  return RawGetDataLength();
}

off_t PWAVFile::RawGetDataLength()
{
  if (isValidWAV) {
    // Updates data length before returns.
    lenData = PFile::GetLength() - lenHeader;
    return lenData;
  }
  else
    return 0;
}


BOOL PWAVFile::SetFormat(unsigned fmt)
{
  if (IsOpen() || isValidWAV)
    return FALSE;

  SelectFormat(fmt);

  return TRUE;
}

BOOL PWAVFile::SetFormat(const PString & format)
{
  if (IsOpen() || isValidWAV)
    return FALSE;

  SelectFormat(format);

  return TRUE;
}

static inline BOOL NeedsConverter(const PWAV::FMTChunk & fmtChunk)
{
  return (fmtChunk.format != PWAVFile::fmt_PCM) || (fmtChunk.bitsPerSample != 16);
}

BOOL PWAVFile::ProcessHeader() 
{
  if (autoConverter != NULL) {
    delete autoConverter;
    autoConverter = NULL;
  }

  // Process the header information
  // This comes in 3 or 4 chunks, either RIFF, FORMAT and DATA
  // or RIFF, FORMAT, FACT and DATA.

  if (!IsOpen()) {
    PTRACE(1,"WAV\tProcessHeader: Not Open");
    return (FALSE);
  }

  // go to the beginning of the file
  if (!PFile::SetPosition(0)) {
    PTRACE(1,"WAV\tProcessHeader: Cannot Set Pos");
    return (FALSE);
  }

  // Read the RIFF chunk.
  struct PWAV::RIFFChunkHeader riffChunk;
  if (!ReadAndCheck(*this, &riffChunk, sizeof(riffChunk)))
    return FALSE;

  // check if tags are correct
  if (strncmp(riffChunk.hdr.tag, WAVLabelRIFF, sizeof(WAVLabelRIFF)) != 0) {
    PTRACE(1,"WAV\tProcessHeader: Not RIFF");
    return (FALSE);
  }

  if (strncmp(riffChunk.tag, WAVLabelWAVE, sizeof(WAVLabelWAVE)) != 0) {
    PTRACE(1,"WAV\tProcessHeader: Not WAVE");
    return (FALSE);
  }

  // Read the known part of the FORMAT chunk.
  if (!ReadAndCheck(*this, &wavFmtChunk, sizeof(wavFmtChunk)))
    return FALSE;

  // check if labels are correct
  if (strncmp(wavFmtChunk.hdr.tag, WAVLabelFMT_, sizeof(WAVLabelFMT_)) != 0) {
    PTRACE(1,"WAV\tProcessHeader: Not FMT");
    return (FALSE);
  }

  // if we opened the file without knowing the format, then try and set the format now
  if (formatHandler == NULL) {
    SelectFormat(wavFmtChunk.format);
    if (formatHandler == NULL) {
      Close();
      return FALSE;
    }
  }

  // read the extended format chunk (if any)
  extendedHeader.SetSize(0);
  if ((unsigned)wavFmtChunk.hdr.len > (sizeof(wavFmtChunk) - sizeof(wavFmtChunk.hdr))) {
    extendedHeader.SetSize(wavFmtChunk.hdr.len - (sizeof(wavFmtChunk) - sizeof(wavFmtChunk.hdr)));
    if (!ReadAndCheck(*this, extendedHeader.GetPointer(), extendedHeader.GetSize()))
      return FALSE;
  }

  // give format handler a chance to read extra chunks
  if (!formatHandler->ReadExtraChunks(*this))
    return FALSE;

  PWAV::ChunkHeader chunkHeader;

  // ignore chunks until we see a DATA chunk
  for (;;) {
    if (!ReadAndCheck(*this, &chunkHeader, sizeof(chunkHeader)))
      return FALSE;
    if (strncmp(chunkHeader.tag, WAVLabelDATA, sizeof(WAVLabelDATA)) == 0) 
      break;
    if (!PFile::SetPosition(PFile::GetPosition() + + chunkHeader.len)) {
      PTRACE(1,"WAV\tProcessHeader: Cannot set new position");
      return FALSE;
    }
  }

  // calculate the size of header and data for accessing the WAV data.
  lenHeader  = PFile::GetPosition(); 
  lenData    = chunkHeader.len;

  // get ptr to data handler if in autoconvert mode
  if (autoConvert && NeedsConverter(wavFmtChunk)) {
    autoConverter = PWAVFileConverterFactory::CreateInstance(wavFmtChunk.format);
    if (autoConverter == NULL) {
      PTRACE(1, "PWAVFile\tNo format converter for type " << (int)wavFmtChunk.format);
    }
  }

  formatHandler->OnStart();

  return TRUE;
}


// Generates the wave file header.
// Two types of header are supported.
// a) PCM data, set to 8000Hz, mono, 16-bit samples
// b) G.723.1 data
// When this function is called with lenData < 0, it will write the header
// as if the lenData is LONG_MAX minus header length.
// Note: If it returns FALSE, the file may be left in inconsistent state.

BOOL PWAVFile::GenerateHeader()
{
  if (autoConverter != NULL) {
    autoConverter = NULL;
  }

  if (!IsOpen()) {
    PTRACE(1, "WAV\tGenerateHeader: Not Open");
    return (FALSE);
  }

  // length of audio data is set to a large value if lenData does not
  // contain a valid (non negative) number. We must then write out real values
  // when we close the wav file.
  int audioDataLen;
  if (lenData < 0) {
    audioDataLen = LONG_MAX - wavFmtChunk.hdr.len;
    header_needs_updating = TRUE;
  } else {
    audioDataLen = lenData;
  }

  // go to the beginning of the file
  if (!PFile::SetPosition(0)) {
    PTRACE(1,"WAV\tGenerateHeader: Cannot Set Pos");
    return (FALSE);
  }

  // write the WAV file header
  PWAV::RIFFChunkHeader riffChunk;
  memcpy(riffChunk.hdr.tag, WAVLabelRIFF, sizeof(WAVLabelRIFF));
  memcpy(riffChunk.tag,     WAVLabelWAVE, sizeof(WAVLabelWAVE));
  riffChunk.hdr.len = lenHeader + audioDataLen - sizeof(riffChunk.hdr);

  if (!WriteAndCheck(*this, &riffChunk, sizeof(riffChunk)))
    return FALSE;

  // populate and write the WAV header with the default data
  memcpy(wavFmtChunk.hdr.tag,  WAVLabelFMT_, sizeof(WAVLabelFMT_));
  wavFmtChunk.hdr.len = sizeof(wavFmtChunk) - sizeof(wavFmtChunk.hdr);  // set default length assuming no extra bytes

  // allow the format handler to modify the header and extra bytes
  if(formatHandler == NULL){
    PTRACE(1,"WAV\tGenerateHeader: format handler is null!");
    return FALSE;
  }
  formatHandler->CreateHeader(wavFmtChunk, extendedHeader);

  // write the basic WAV header
  if (
      !WriteAndCheck(*this, &wavFmtChunk, sizeof(wavFmtChunk)) ||
      ((extendedHeader.GetSize() > 0) && !WriteAndCheck(*this, extendedHeader.GetPointer(), extendedHeader.GetSize()))
     )
    return FALSE;

  // allow the format handler to write additional chunks
  if (!formatHandler->WriteExtraChunks(*this))
    return FALSE;

  // Write the DATA chunk.
  PWAV::ChunkHeader dataChunk;
  memcpy(dataChunk.tag, WAVLabelDATA, sizeof(WAVLabelDATA));
  dataChunk.len = audioDataLen;
  if (!WriteAndCheck(*this, &dataChunk, sizeof(dataChunk)))
    return FALSE;

  isValidWAV = TRUE;

  // get the length of the header
  lenHeader = PFile::GetPosition();

  // get pointer to auto converter 
  if (autoConvert && NeedsConverter(wavFmtChunk)) {
    autoConverter = PWAVFileConverterFactory::CreateInstance(wavFmtChunk.format);

⌨️ 快捷键说明

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