1 // -------------------------------------------------------------------------- 
   5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999 
   7 // -------------------------------------------------------------------------- 
   9 #pragma implementation "sndwav.cpp" 
  12 #include "wx/wxprec.h" 
  22 #include "wx/stream.h" 
  23 #include "wx/datstrm.h" 
  24 #include "wx/filefn.h" 
  25 #include "wx/mstream.h" 
  27 #include "wx/mmedia/sndbase.h" 
  28 #include "wx/mmedia/sndcodec.h" 
  29 #include "wx/mmedia/sndfile.h" 
  30 #include "wx/mmedia/sndpcm.h" 
  31 #include "wx/mmedia/sndg72x.h" 
  32 #include "wx/mmedia/sndmsad.h" 
  33 #include "wx/mmedia/sndwav.h" 
  35 #define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16)  | (((wxUint32)d) << 24))  
  37 #define RIFF_SIGNATURE BUILD_SIGNATURE('R','I','F','F') 
  38 #define WAVE_SIGNATURE BUILD_SIGNATURE('W','A','V','E') 
  39 #define FMT_SIGNATURE BUILD_SIGNATURE('f','m','t',' ') 
  40 #define DATA_SIGNATURE BUILD_SIGNATURE('d','a','t','a') 
  42 #define HEADER_SIZE 4+4 + 4+4+16 + 4+4 
  46 wxSoundWave::wxSoundWave(wxInputStream
& stream
, wxSoundStream
& io_sound
) 
  47         : wxSoundFileStream(stream
, io_sound
) 
  49     m_base_offset 
= wxInvalidOffset
; 
  52 wxSoundWave::wxSoundWave(wxOutputStream
& stream
, wxSoundStream
& io_sound
) 
  53         : wxSoundFileStream(stream
, io_sound
) 
  55     m_base_offset 
= wxInvalidOffset
; 
  58 wxSoundWave::~wxSoundWave() 
  62 wxString 
wxSoundWave::GetCodecName() const 
  64     return wxString(wxT("wxSoundWave codec")); 
  67 #define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; } 
  69 bool wxSoundWave::CanRead() 
  71     wxUint32 len
, signature1
, signature2
; 
  72     m_snderror 
= wxSOUND_NOERROR
; 
  74     // Test the main signatures: 
  76     FAIL_WITH(m_input
->Read(&signature1
, 4).LastRead() != 4, wxSOUND_INVSTRM
); 
  78     if (wxUINT32_SWAP_ON_BE(signature1
) != RIFF_SIGNATURE
) { 
  79         m_input
->Ungetch(&signature1
, 4); 
  83     // Pass the global length 
  84     m_input
->Read(&len
, 4); 
  85     FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
); 
  87     // Get the second signature 
  88     FAIL_WITH(m_input
->Read(&signature2
, 4).LastRead() != 4, wxSOUND_INVSTRM
); 
  90     m_input
->Ungetch(&signature2
, 4); 
  91     m_input
->Ungetch(&len
, 4); 
  92     m_input
->Ungetch(&signature1
, 4); 
  94     // Test the second signature 
  95     if (wxUINT32_SWAP_ON_BE(signature2
) != WAVE_SIGNATURE
) 
 101 bool wxSoundWave::HandleOutputPCM(wxDataInputStream
& WXUNUSED(data
), wxUint32 len
, 
 103                                   wxUint32 sample_fq
, wxUint32 
WXUNUSED(byte_p_sec
), 
 104                                   wxUint16 
WXUNUSED(byte_p_spl
), wxUint16 bits_p_spl
) 
 106     wxSoundFormatPcm sndformat
; 
 108     sndformat
.SetSampleRate(sample_fq
); 
 109     sndformat
.SetBPS(bits_p_spl
); 
 110     sndformat
.SetChannels(channels
); 
 111     sndformat
.Signed(TRUE
); 
 112     sndformat
.SetOrder(wxLITTLE_ENDIAN
); 
 114     if (!SetSoundFormat(sndformat
)) 
 117     m_input
->SeekI(len
, wxFromCurrent
); 
 122 bool wxSoundWave::HandleOutputMSADPCM(wxDataInputStream
& data
, wxUint32 len
, 
 124                                       wxUint32 sample_fq
, wxUint32 
WXUNUSED(byte_p_sec
), 
 125                                       wxUint16 
WXUNUSED(byte_p_spl
), wxUint16 
WXUNUSED(bits_p_spl
)) 
 127     wxSoundFormatMSAdpcm sndformat
; 
 129     wxUint16 coefs_len
, i
; 
 132     sndformat
.SetSampleRate(sample_fq
); 
 133     sndformat
.SetChannels(channels
); 
 135     block_size 
= data
.Read16(); 
 136     coefs_len 
= data
.Read16(); 
 138     coefs
[0] = new wxInt16
[coefs_len
]; 
 139     coefs
[1] = new wxInt16
[coefs_len
]; 
 141     for (i
=0;i
<coefs_len
;i
++) { 
 142         coefs
[0][i
] = data
.Read16(); 
 143         coefs
[1][i
] = data
.Read16(); 
 146     sndformat
.SetCoefs(coefs
, 2, coefs_len
); 
 147     sndformat
.SetBlockSize(block_size
); 
 152     if (!SetSoundFormat(sndformat
)) 
 155     len 
-= coefs_len
*4 + 4; 
 157     m_input
->SeekI(len
, wxFromCurrent
); 
 162 bool wxSoundWave::HandleOutputG721(wxDataInputStream
& WXUNUSED(data
), wxUint32 len
, 
 163                                    wxUint16 
WXUNUSED(channels
), 
 164                                    wxUint32 sample_fq
, wxUint32 
WXUNUSED(byte_p_sec
), 
 165                                    wxUint16 
WXUNUSED(byte_p_spl
), wxUint16 
WXUNUSED(bits_p_spl
)) 
 167     wxSoundFormatG72X sndformat
; 
 169     sndformat
.SetSampleRate(sample_fq
); 
 170     sndformat
.SetG72XType(wxSOUND_G721
); 
 172     if (!SetSoundFormat(sndformat
)) 
 175     m_input
->SeekI(len
, wxFromCurrent
); 
 180 bool wxSoundWave::PrepareToPlay() 
 182     wxUint32 signature
, len
; 
 186         m_snderror 
= wxSOUND_INVSTRM
; 
 190     wxDataInputStream 
data(*m_input
); 
 191     data
.BigEndianOrdered(FALSE
); 
 193     // Get the first signature 
 194     FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
); 
 195     FAIL_WITH(wxUINT32_SWAP_ON_BE(signature
) != RIFF_SIGNATURE
, wxSOUND_INVSTRM
); 
 199     FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
); 
 202     // Get the second signature 
 203     FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
); 
 204     FAIL_WITH(wxUINT32_SWAP_ON_BE(signature
) != WAVE_SIGNATURE
, wxSOUND_INVSTRM
); 
 209     while (!end_headers
) { 
 210         FAIL_WITH(m_input
->Read(&signature
, 4).LastRead() != 4, wxSOUND_INVSTRM
); 
 213         FAIL_WITH(m_input
->LastRead() != 4, wxSOUND_INVSTRM
); 
 215         switch (wxUINT32_SWAP_ON_BE(signature
)) { 
 216             case FMT_SIGNATURE
: {  // "fmt " 
 217                 wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
; 
 218                 wxUint32 sample_fq
, byte_p_sec
; 
 220                 // Get the common parameters 
 221                 data 
>> format 
>> channels 
>> sample_fq 
 
 222                      >> byte_p_sec 
>> byte_p_spl 
>> bits_p_spl
; 
 227                         if (!HandleOutputPCM(data
, len
, channels
, sample_fq
, 
 228                                              byte_p_sec
, byte_p_spl
, 
 232                     case 0x02: // MS ADPCM 
 233                         if (!HandleOutputMSADPCM(data
, len
, 
 235                                                  byte_p_sec
, byte_p_spl
, 
 240                         if (!HandleOutputG721(data
, len
, 
 242                                               byte_p_sec
, byte_p_spl
, 
 247                         m_snderror 
= wxSOUND_NOCODEC
; 
 252             case DATA_SIGNATURE
: // "data" 
 253                 m_base_offset 
= m_input
->TellI(); 
 255                 FinishPreparation(len
); 
 259                 m_input
->SeekI(len
, wxFromCurrent
); 
 266 wxSoundFormatBase 
*wxSoundWave::HandleInputPCM(wxDataOutputStream
& data
) 
 268     wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
; 
 269     wxUint32 sample_fq
, byte_p_sec
; 
 270     wxSoundFormatPcm 
*pcm
; 
 272     pcm 
= (wxSoundFormatPcm 
*)(m_sndformat
->Clone()); 
 274     // Write block length 
 277     sample_fq  
= pcm
->GetSampleRate(); 
 278     bits_p_spl 
= pcm
->GetBPS(); 
 279     channels   
= pcm
->GetChannels(); 
 280     byte_p_spl 
= pcm
->GetBPS() / 8; 
 281     byte_p_sec 
= pcm
->GetBytesFromTime(1); 
 285     pcm
->SetOrder(wxLITTLE_ENDIAN
); 
 287     data 
<< format 
<< channels 
<< sample_fq
 
 288          << byte_p_sec 
<< byte_p_spl 
<< bits_p_spl
; 
 293 wxSoundFormatBase 
*wxSoundWave::HandleInputG72X(wxDataOutputStream
& data
) 
 295     wxUint16 format
, channels
, byte_p_spl
, bits_p_spl
; 
 296     wxUint32 sample_fq
, byte_p_sec
; 
 297     wxSoundFormatG72X 
*g72x
; 
 299     // Write block length 
 302     g72x 
= (wxSoundFormatG72X 
*)(m_sndformat
->Clone()); 
 303     if (g72x
->GetG72XType() != wxSOUND_G721
) { 
 308     sample_fq  
= g72x
->GetSampleRate(); 
 312     byte_p_sec 
= g72x
->GetBytesFromTime(1); 
 314     data 
<< format 
<< channels 
<< sample_fq
 
 315          << byte_p_sec 
<< byte_p_spl 
<< bits_p_spl
; 
 320 bool wxSoundWave::PrepareToRecord(wxUint32 time
) 
 322 #define WRITE_SIGNATURE(s,sig) \ 
 324 signature = wxUINT32_SWAP_ON_BE(signature); \ 
 325 FAIL_WITH(s->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM); 
 328     wxMemoryOutputStream fmt_data
; 
 331         m_snderror 
= wxSOUND_INVSTRM
; 
 335     wxDataOutputStream 
data(*m_output
); 
 336     wxDataOutputStream 
fmt_d_data(fmt_data
); 
 338     data
.BigEndianOrdered(FALSE
); 
 339     fmt_d_data
.BigEndianOrdered(FALSE
); 
 341     WRITE_SIGNATURE(m_output
, RIFF_SIGNATURE
); 
 343     FAIL_WITH(m_output
->LastWrite() != 4, wxSOUND_INVSTRM
); 
 345     WRITE_SIGNATURE((&fmt_data
), WAVE_SIGNATURE
); 
 348         wxSoundFormatBase 
*frmt
; 
 350         WRITE_SIGNATURE((&fmt_data
), FMT_SIGNATURE
); 
 352         switch (m_sndformat
->GetType()) { 
 354                 frmt 
= HandleInputPCM(fmt_d_data
); 
 357                 frmt 
= HandleInputG72X(fmt_d_data
); 
 360                 m_snderror 
= wxSOUND_NOCODEC
; 
 364         FAIL_WITH(!frmt
, wxSOUND_NOCODEC
); 
 366         if (!SetSoundFormat(*frmt
)) { 
 374     data 
<< (fmt_data
.GetSize() + m_sndformat
->GetBytesFromTime(time
)); 
 376     // We, finally, copy the header block to the output stream  
 379         out_buf 
= new char[fmt_data
.GetSize()]; 
 381         fmt_data
.CopyTo(out_buf
, fmt_data
.GetSize()); 
 382         m_output
->Write(out_buf
, fmt_data
.GetSize()); 
 387     WRITE_SIGNATURE(m_output
, DATA_SIGNATURE
); 
 388     data
.Write32(m_sndformat
->GetBytesFromTime(time
)); 
 392 bool wxSoundWave::FinishRecording() 
 394     if (m_output
->SeekO(0, wxFromStart
) == wxInvalidOffset
) 
 395         // We can't but there is no error. 
 398     if (m_bytes_left 
== 0) 
 401     // TODO: Update headers when we stop before the specified time (if possible) 
 405 bool wxSoundWave::RepositionStream(wxUint32 
WXUNUSED(position
)) 
 407     if (m_base_offset 
== wxInvalidOffset
) 
 409     m_input
->SeekI(m_base_offset
, wxFromStart
); 
 413 wxUint32 
wxSoundWave::GetData(void *buffer
, wxUint32 len
) 
 415     return m_input
->Read(buffer
, len
).LastRead(); 
 418 wxUint32 
wxSoundWave::PutData(const void *buffer
, wxUint32 len
) 
 420     return m_output
->Write(buffer
, len
).LastWrite();