www.pudn.com > w_ipp-sample-media_p_5.0.017.zip > wav_file.cpp


/*////////////////////////////////////////////////////////////////////////////// 
// 
//                  INTEL CORPORATION PROPRIETARY INFORMATION 
//     This software is supplied under the terms of a license agreement or 
//     nondisclosure agreement with Intel Corporation and may not be copied 
//     or disclosed except in accordance with the terms of that agreement. 
//          Copyright(c) 2004-2005 Intel Corporation. All Rights Reserved. 
// 
*/ 
 
#include  
#include  
#include "wav_file.h" 
#include "umc_structures.h" 
 
WavFile::WavFile() 
{ 
  m_is_first_time = 1; 
  m_is_info_valid = 0; 
  m_file_handle = NULL; 
  m_info.channels_number = 1; 
} 
 
WavFile::~WavFile() 
{ 
} 
 
int WavFile::Open(vm_char *p_filename, 
                  unsigned int mode) 
{ 
  int res; 
  FILE   *p_file = NULL; 
 
  if (mode & AFM_CREATE) { 
    p_file = vm_file_open(p_filename, __VM_STRING("wb")); 
  } else { 
    p_file = vm_file_open(p_filename, __VM_STRING("rb")); 
  } 
  if (p_file == NULL) { 
    return -1; 
  } 
  m_file_handle = p_file; 
 
  if (!(mode & AFM_CREATE)) { 
    res = ReadHeaderInfo(); 
    if (res < 0) { 
      if (mode & AFM_NO_CONTENT_WRN) { 
        fseek((FILE *) m_file_handle, 0, SEEK_SET); 
        return 1; 
      } 
      fclose((FILE *) m_file_handle); 
      return -1; 
    } 
  } 
  return 0; 
} 
 
const vm_var32 ctRiff = 0x46464952; 
const vm_var32 ctWave = 0x45564157; 
const vm_var32 ctFmt = 0x20746D66; 
const vm_var32 ctData = 0x61746164; 
 
struct t_chunk { 
  vm_var32 m_ulId; 
  vm_var32 m_ulSize; 
}; 
 
const vm_var32 ctFmtSize = (2 + 2 + 4 + 4 + 2 + 2); 
 
typedef struct { 
  vm_var32 id_riff; 
  vm_var32 len_riff; 
 
  vm_var32 id_chuck; 
  vm_var32 fmt; 
  vm_var32 len_chuck; 
 
  vm_var16 type; 
  vm_var16 channels; 
  vm_var32 freq; 
  vm_var32 bytes; 
  vm_var16 align; 
  vm_var16 bits; 
 
  vm_var32 id_data; 
  vm_var32 len_data; 
} sWaveHeader; 
 
struct wav_header { 
  t_chunk riff_chunk; 
  vm_var32 wave_signature; 
  t_chunk fmt_chunk; 
 
  vm_var16 nFormatTag; 
  vm_var16 nChannels; 
  vm_var32 nSamplesPerSec; 
  vm_var32 nAvgBytesPerSec; 
  vm_var16 nBlockAlign; 
  vm_var16 wBitPerSample; 
 
  t_chunk data_chunk; 
}; 
 
struct wav_header_ex { 
  t_chunk riff_chunk; 
  unsigned int wave_signature; 
  t_chunk fmt_chunk; 
 
  vm_var16 nFormatTag; 
  vm_var16 nChannels; 
  vm_var32 nSamplesPerSec; 
  vm_var32 nAvgBytesPerSec; 
  vm_var16 nBlockAlign; 
  vm_var16 wBitPerSample; 
  vm_var16 cbSize; 
 
  union { 
    vm_var16 wValidBitsPerSample; /* bits of precision */ 
    vm_var16 wSamplesPerBlock;    /* valid if wBitsPerSample==0 */ 
    vm_var16 wReserved;   /* If neither applies, set to zero. */ 
  }; 
 
  vm_var32 dwChannelMask; 
  vm_var16 guid[16]; 
 
  t_chunk data_chunk; 
}; 
 
int WavFile::Read(void *p_data, 
                  size_t size) 
{ 
  int n; 
#ifdef _BIG_ENDIAN_ 
  int i, bsnum; 
#endif 
 
  if (m_file_handle == NULL) { 
    return -1; 
  } 
 
  n = fread(p_data, 1, size, (FILE *) m_file_handle); 
 
#ifdef _BIG_ENDIAN_ 
  bsnum = m_info.resolution >> 3; 
 
  if(bsnum == 2) 
    for (i = 0; i < n/2; i++) 
      ((vm_var16*)p_data)[i] = BIG_ENDIAN_SWAP16(((vm_var16*)p_data)[i]); 
  else if (bsnum == 3) { 
      for (i = 0; i < n/3; i++) { 
          vm_var8 t0; 
 
          t0 = ((vm_var8*)p_data)[3*i]; 
          ((vm_var8*)p_data)[3*i] = ((vm_var8*)p_data)[3*i+2]; 
          ((vm_var8*)p_data)[3*i+2] = t0; 
      } 
  } 
  else if(bsnum == 4) 
    for (i = 0; i < n/4; i++) 
      ((vm_var32*)p_data)[i] = BIG_ENDIAN_SWAP32(((vm_var32*)p_data)[i]); 
#endif 
 
  return n; 
} 
 
int WavFile::Write(void *p_data, 
                   size_t size) 
{ 
#ifdef _BIG_ENDIAN_ 
  int i; 
#endif 
  size_t n; 
  size_t header_size; 
  vm_var16  *buf = (vm_var16 *)p_data; 
 
//  wav_header    header; 
  wav_header_ex header_ex; 
 
  if (m_is_first_time) { 
    m_is_first_time = 0; 
 
// header_size = sizeof(wav_header_ex); 
    header_size = sizeof(sWaveHeader); 
    fseek((FILE *) m_file_handle, header_size, SEEK_SET); 
 
    m_riff_size = header_size - 4; 
    m_data_size = 0; 
  } 
//  header_size = sizeof(wav_header_ex); 
 
  if (m_file_handle == NULL) { 
    return -1; 
  } 
 
#ifdef _BIG_ENDIAN_ 
  for (i = 0; i < size/2; i++) 
    ((vm_var16*)p_data)[i] = BIG_ENDIAN_SWAP16(((vm_var16*)p_data)[i]); 
#endif 
  n = fwrite(p_data, 1, size, (FILE *) m_file_handle); 
 
  m_riff_size += size; 
  m_data_size += size; 
 
  return n; 
} 
 
int WavFile::Close() 
{ 
  int n, b, bits; 
  sWaveHeader wave; 
  int nCh = m_info.channels_number; 
  int CntFrameMulLenFrame = m_data_size / nCh / 2; 
 
// wav_header wave; 
 
  if (m_file_handle == NULL) { 
    return -1; 
  } 
 
  if (m_is_first_time) { 
    m_is_first_time = 0; 
    m_riff_size = sizeof(sWaveHeader) - 4; 
    m_data_size = 0; 
  } 
//--------------------- 
 
  bits = 16; 
 
  wave.id_riff = BIG_ENDIAN_SWAP32(0x46464952); 
  wave.len_riff =BIG_ENDIAN_SWAP32(sizeof(sWaveHeader) + ((CntFrameMulLenFrame) << 1) * nCh - 8); 
 
  wave.id_chuck = BIG_ENDIAN_SWAP32(0x45564157); 
  wave.fmt = BIG_ENDIAN_SWAP32(0x20746D66); 
  wave.len_chuck = BIG_ENDIAN_SWAP32(0x00000010); 
 
  wave.type = BIG_ENDIAN_SWAP16(0x0001); 
  wave.channels = BIG_ENDIAN_SWAP16(nCh); 
  wave.freq = BIG_ENDIAN_SWAP32((vm_var32)(m_info.sample_rate)); 
  wave.bytes = BIG_ENDIAN_SWAP32((m_info.sample_rate << 1) * nCh); 
  wave.align = BIG_ENDIAN_SWAP16((vm_var16)((nCh * bits) / 8)); 
  wave.bits = BIG_ENDIAN_SWAP16((vm_var16)bits); 
 
  wave.id_data = BIG_ENDIAN_SWAP32(0x61746164); 
  wave.len_data = BIG_ENDIAN_SWAP32(((CntFrameMulLenFrame) << 1) * nCh); 
 
  fseek((FILE *) m_file_handle, 0, SEEK_SET); 
  n = fwrite(&wave, 1, sizeof(sWaveHeader), (FILE *) m_file_handle); 
 
  fclose((FILE *) m_file_handle); 
  return 0; 
} 
 
int WavFile::SetInfo(Info * p_info) 
{ 
  m_is_info_valid = 1; 
 
  memcpy(&m_info, p_info, sizeof(m_info)); 
 
  return 0; 
} 
 
int WavFile::GetInfo(Info * p_info) 
{ 
  if (m_is_info_valid) { 
    memcpy(p_info, &m_info, sizeof(m_info)); 
    return 0; 
  } 
  return -1; 
} 
 
int WavFile::ReadHeaderInfo() 
{ 
  wav_header_ex header; 
  t_chunk xChunk; 
  vm_var32 m_ulId = 0; 
  vm_var32 m_ulSize = 0; 
 
  vm_var32 ulTemp = 0; 
  vm_var32 ulOffset = 0; 
  vm_var32 ulDataChunkOffset = 0; 
  int iFmtOk = 0; 
  int iDataOk = 0; 
 
  if (fread(&xChunk, sizeof(xChunk), 1, (FILE *) m_file_handle) != 1) { 
// / IO error 
    return -1; 
  } 
  m_ulId = BIG_ENDIAN_SWAP32(xChunk.m_ulId); 
  m_ulSize = BIG_ENDIAN_SWAP32(xChunk.m_ulSize); 
  if (m_ulId != ctRiff) { 
// / File does not contain 'Riff' chunk ! 
    return -2; 
  } 
  if (fread(&ulTemp, sizeof(ulTemp), 1, (FILE *) m_file_handle) != 1) { 
// / IO error 
    return -1; 
  } 
  if (ulTemp != BIG_ENDIAN_SWAP32(ctWave)) { 
// / File does not contain 'Wave' signature ! 
    return -3; 
  } 
 
  while (1) { 
    if (iFmtOk && iDataOk) 
      break; 
    ulOffset = ftell((FILE *) m_file_handle); 
 
    if (fread(&xChunk, sizeof(xChunk), 1, (FILE *) m_file_handle) != 1) { 
// / IO error 
      return -1; 
    } 
 
    m_ulId = BIG_ENDIAN_SWAP32(xChunk.m_ulId); 
    m_ulSize = BIG_ENDIAN_SWAP32(xChunk.m_ulSize); 
 
    switch (m_ulId) { 
    case ctFmt: 
      if (fread(&header.nFormatTag, ctFmtSize, 1, (FILE *) m_file_handle) != 1) { 
// / IO error 
        return -1; 
      } 
      if (m_ulSize > ctFmtSize) { 
        fseek((FILE *) m_file_handle, m_ulSize - ctFmtSize, SEEK_CUR); 
      } 
      iFmtOk = 1; 
      break; 
    case ctData: 
      ulDataChunkOffset = ulOffset; 
      fseek((FILE *) m_file_handle, m_ulSize, SEEK_CUR); 
      iDataOk = 1; 
      break; 
    default: 
      fseek((FILE *) m_file_handle, m_ulSize, SEEK_CUR); 
      break; 
    } 
  } 
  fseek((FILE *) m_file_handle, ulDataChunkOffset + 8, SEEK_SET); 
 
  m_info.format_tag = BIG_ENDIAN_SWAP16(header.nFormatTag); 
  m_info.sample_rate = BIG_ENDIAN_SWAP32(header.nSamplesPerSec); 
  m_info.resolution = BIG_ENDIAN_SWAP16(header.wBitPerSample); 
  m_info.channels_number = BIG_ENDIAN_SWAP16(header.nChannels); 
  m_info.channel_mask = 0; 
  m_is_info_valid = 1; 
 
//    m_info 
 
  return 0; 
}