1// -------------------------------------------------------------------------- 2// Name: sndaiff.cpp 3// Purpose: 4// Date: 08/11/1999 5// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999 6// CVSID: $Id: sndaiff.cpp 35650 2005-09-23 12:56:45Z MR $ 7// wxWindows licence 8// -------------------------------------------------------------------------- 9 10#include "wx/wxprec.h" 11 12#ifndef WX_PRECOMP 13 #include "wx/defs.h" 14#endif 15 16#ifdef __BORLANDC__ 17 #pragma hdrstop 18#endif 19 20#include "wx/stream.h" 21#include "wx/datstrm.h" 22#include "wx/filefn.h" 23 24#include "wx/mmedia/sndbase.h" 25#include "wx/mmedia/sndcodec.h" 26#include "wx/mmedia/sndfile.h" 27#include "wx/mmedia/sndpcm.h" 28#include "wx/mmedia/sndaiff.h" 29 30#define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24)) 31 32#define FORM_SIGNATURE BUILD_SIGNATURE('F','O','R','M') 33#define AIFF_SIGNATURE BUILD_SIGNATURE('A','I','F','F') 34#define AIFC_SIGNATURE BUILD_SIGNATURE('A','I','F','C') 35#define COMM_SIGNATURE BUILD_SIGNATURE('C','O','M','M') 36#define SSND_SIGNATURE BUILD_SIGNATURE('S','S','N','D') 37 38wxSoundAiff::wxSoundAiff(wxInputStream& stream, wxSoundStream& io_sound) 39 : wxSoundFileStream(stream, io_sound) 40{ 41 m_base_offset = wxInvalidOffset; 42} 43 44wxSoundAiff::wxSoundAiff(wxOutputStream& stream, wxSoundStream& io_sound) 45 : wxSoundFileStream(stream, io_sound) 46{ 47 m_base_offset = wxInvalidOffset; 48} 49 50wxSoundAiff::~wxSoundAiff() 51{ 52} 53 54wxString wxSoundAiff::GetCodecName() const 55{ 56 return wxT("wxSoundAiff codec"); 57} 58 59bool wxSoundAiff::CanRead() 60{ 61 wxUint32 signature1, signature2, len; 62 63 if (m_input->Read(&signature1, 4).LastRead() != 4) 64 return false; 65 66 if (wxUINT32_SWAP_ON_BE(signature1) != FORM_SIGNATURE) { 67 m_input->Ungetch(&signature1, 4); 68 return false; 69 } 70 71 m_input->Read(&len, 4); 72 if (m_input->LastRead() != 4) { 73 m_input->Ungetch(&len, m_input->LastRead()); 74 m_input->Ungetch(&signature1, 4); 75 return false; 76 } 77 78 if (m_input->Read(&signature2, 4).LastRead() != 4) { 79 m_input->Ungetch(&signature2, m_input->LastRead()); 80 m_input->Ungetch(&len, 4); 81 m_input->Ungetch(&signature1, 4); 82 return false; 83 } 84 85 m_input->Ungetch(&signature2, 4); 86 m_input->Ungetch(&len, 4); 87 m_input->Ungetch(&signature1, 4); 88 89 if ( 90 wxUINT32_SWAP_ON_BE(signature2) != AIFF_SIGNATURE && 91 wxUINT32_SWAP_ON_BE(signature2) != AIFC_SIGNATURE) 92 return false; 93 94 return true; 95} 96 97#define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return false; } 98 99bool wxSoundAiff::PrepareToPlay() 100{ 101 wxDataInputStream data(*m_input); 102 wxUint32 signature, len, ssnd; 103 bool end_headers; 104 105 if (!m_input) { 106 m_snderror = wxSOUND_INVSTRM; 107 return false; 108 } 109 m_snderror = wxSOUND_NOERROR; 110 111 data.BigEndianOrdered(true); 112 113 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM); 114 FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != FORM_SIGNATURE, wxSOUND_INVSTRM); 115 // "FORM" 116 117 len = data.Read32(); 118 wxUnusedVar(len); 119 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM); 120 // dummy len 121 122 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM); 123 FAIL_WITH( 124 wxUINT32_SWAP_ON_BE(signature) != AIFF_SIGNATURE && 125 wxUINT32_SWAP_ON_BE(signature) != AIFC_SIGNATURE, wxSOUND_INVSTRM); 126 // "AIFF" / "AIFC" 127 128 end_headers = false; 129 while (!end_headers) { 130 FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM); 131 132 len = data.Read32(); 133 FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM); 134 135 switch (wxUINT32_SWAP_ON_BE(signature)) { 136 case COMM_SIGNATURE: { // "COMM" 137 wxUint16 channels, bps; 138 wxUint32 num_samples; 139 double srate; 140 wxSoundFormatPcm sndformat; 141 142 // Get sound data informations 143 data >> channels >> num_samples >> bps >> srate; 144 145 // Convert them in a wxSoundFormat object 146 sndformat.SetSampleRate((wxUint32) srate); 147 sndformat.SetBPS(bps); 148 sndformat.SetChannels(channels); 149 sndformat.Signed(false); 150 sndformat.SetOrder(wxBIG_ENDIAN); 151 152 if (!SetSoundFormat(sndformat)) 153 return false; 154 // We pass all data left 155 m_input->SeekI(len-18, wxFromCurrent); 156 break; 157 } 158 case SSND_SIGNATURE: { // "SSND" 159 data >> ssnd; 160 // m_input->SeekI(4, wxFromCurrent); // Pass an INT32 161 // m_input->SeekI(len-4, wxFromCurrent); // Pass the rest 162 m_input->SeekI(ssnd + 4, wxFromCurrent); 163 m_base_offset = m_input->TellI(); 164 // len-8 bytes of samples 165 FinishPreparation(len - 8); 166 end_headers = true; 167 break; 168 } 169 default: 170 m_input->SeekI(len, wxFromCurrent); 171 break; 172 } 173 } 174 return true; 175} 176 177bool wxSoundAiff::PrepareToRecord(wxUint32 WXUNUSED(time)) 178{ 179 // TODO 180 return false; 181} 182 183bool wxSoundAiff::FinishRecording() 184{ 185 // TODO 186 return false; 187} 188 189bool wxSoundAiff::RepositionStream(wxUint32 WXUNUSED(position)) 190{ 191 // If the stream is not seekable "TellI() returns wxInvalidOffset" we cannot reposition stream 192 if (m_base_offset == wxInvalidOffset) 193 return false; 194 m_input->SeekI(m_base_offset, wxFromStart); 195 return true; 196} 197 198wxUint32 wxSoundAiff::GetData(void *buffer, wxUint32 len) 199{ 200 return m_input->Read(buffer, len).LastRead(); 201} 202 203wxUint32 wxSoundAiff::PutData(const void *buffer, wxUint32 len) 204{ 205 return m_output->Write(buffer, len).LastWrite(); 206} 207