kwave  18.07.70
AudiofileDecoder.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  AudiofileDecoder.cpp - import through libaudiofile
3  -------------------
4  begin : Tue May 28 2002
5  copyright : (C) 2002 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 #include <stdlib.h>
20 
21 #include <audiofile.h>
22 
23 #include <QtGlobal>
24 
25 #include <KLocalizedString>
26 
27 #include "libkwave/Compression.h"
28 #include "libkwave/FileInfo.h"
29 #include "libkwave/MessageBox.h"
30 #include "libkwave/MultiWriter.h"
31 #include "libkwave/Sample.h"
32 #include "libkwave/SampleFormat.h"
33 #include "libkwave/Utils.h"
35 #include "libkwave/Writer.h"
36 
37 #include "AudiofileDecoder.h"
38 
39 //***************************************************************************
41  :Kwave::Decoder(), m_source(Q_NULLPTR), m_src_adapter(Q_NULLPTR)
42 {
43  /* defined in RFC 1521 */
44  addMimeType("audio/basic",
45  i18n("NeXT, Sun Audio"),
46  "*.au; *.snd");
47 
48  /* some others, mime types might be wrong (I found no RFC or similar) */
49  addMimeType("audio/x-8svx",
50  i18n("Amiga IFF/8SVX Sound File Format"),
51  "*.iff; *.8svx");
52  addMimeType("audio/x-aifc",
53  i18n("Compressed Audio Interchange Format"),
54  "*.aifc");
55  addMimeType("audio/x-aiff", /* included in KDE */
56  i18n("Audio Interchange Format"),
57  "*.aif; *.aiff");
58  addMimeType("audio/x-avr",
59  i18n("Audio Visual Research File Format"),
60  "*.avr");
61  addMimeType("audio/x-caf",
62  i18n("Core Audio File Format"),
63  "*.caf");
64  addMimeType("audio/x-ircam",
65  i18n("Berkeley, IRCAM, Carl Sound Format"),
66  "*.sf");
67  addMimeType("audio/x-nist",
68  i18n("NIST SPHERE Audio File Format"),
69  "*.nist");
70  addMimeType("audio/x-smp",
71  i18n("Sample Vision Format"),
72  "*.smp");
73  addMimeType("audio/x-voc",
74  i18n("Creative Voice"),
75  "*.voc");
76 }
77 
78 //***************************************************************************
80 {
81  if (m_source) close();
82  if (m_src_adapter) delete m_src_adapter;
83 }
84 
85 //***************************************************************************
87 {
88  return new Kwave::AudiofileDecoder();
89 }
90 
91 //***************************************************************************
92 bool Kwave::AudiofileDecoder::open(QWidget *widget, QIODevice &src)
93 {
94  metaData().clear();
95  Q_ASSERT(!m_source);
96  if (m_source) qWarning("AudiofileDecoder::open(), already open !");
97 
98  // try to open the source
99  if (!src.open(QIODevice::ReadOnly)) {
100  qWarning("AudiofileDecoder::open(), failed to open source !");
101  return false;
102  }
103 
104  // source successfully opened
105  m_source = &src;
107 
108  Q_ASSERT(m_src_adapter);
109  if (!m_src_adapter) return false;
110 
111  m_src_adapter->open(m_src_adapter, Q_NULLPTR);
112 
113  AFfilehandle fh = m_src_adapter->handle();
114  if (!fh || (m_src_adapter->lastError() >= 0)) {
115  QString reason;
116 
117  switch (m_src_adapter->lastError()) {
118  case AF_BAD_NOT_IMPLEMENTED:
119  reason = i18n("Format or function is not implemented");
120  break;
121  case AF_BAD_MALLOC:
122  reason = i18n("Out of memory");
123  break;
124  case AF_BAD_HEADER:
125  reason = i18n("File header is damaged");
126  break;
127  case AF_BAD_CODEC_TYPE:
128  reason = i18n("Invalid codec type");
129  break;
130  case AF_BAD_OPEN:
131  reason = i18n("Opening the file failed");
132  break;
133  case AF_BAD_READ:
134  reason = i18n("Read access failed");
135  break;
136  case AF_BAD_SAMPFMT:
137  reason = i18n("Invalid sample format");
138  break;
139  default:
140  reason = reason.number(m_src_adapter->lastError());
141  }
142 
143  QString text= i18n("An error occurred while opening the "\
144  "file:\n'%1'", reason);
145  Kwave::MessageBox::error(widget, text);
146 
147  return false;
148  }
149 
150  AFframecount length = afGetFrameCount(fh, AF_DEFAULT_TRACK);
151  unsigned int tracks = qMax(afGetVirtualChannels(fh, AF_DEFAULT_TRACK), 0);
152  unsigned int bits = 0;
153  double rate = 0.0;
154  int af_sample_format;
155  afGetVirtualSampleFormat(fh, AF_DEFAULT_TRACK, &af_sample_format,
156  reinterpret_cast<int *>(&bits));
158  switch (af_sample_format)
159  {
160  case AF_SAMPFMT_TWOSCOMP:
162  break;
163  case AF_SAMPFMT_UNSIGNED:
165  break;
166  case AF_SAMPFMT_FLOAT:
168  break;
169  case AF_SAMPFMT_DOUBLE:
171  break;
172  default:
174  break;
175  }
176 
177  // get sample rate, with fallback to 8kHz
178  rate = afGetRate(fh, AF_DEFAULT_TRACK);
179  if (rate < 1.0) {
180  qWarning("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"\
181  "WARNING: file has no sample rate!\n"\
182  " => using 8000 samples/sec as fallback\n"\
183  "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
184  rate = 8000.0;
185  }
186 
188  QString sample_format_name = sf.description(Kwave::SampleFormat(fmt), true);
189 
190  if (static_cast<signed int>(bits) < 0) bits = 0;
191 
192  int af_compression = afGetCompression(fh, AF_DEFAULT_TRACK);
193  const Kwave::Compression compression(
194  Kwave::Compression::fromAudiofile(af_compression)
195  );
196 
197  Kwave::FileInfo info(metaData());
198  info.setRate(rate);
199  info.setBits(bits);
200  info.setTracks(tracks);
201  info.setLength(length);
203  info.set(Kwave::INF_COMPRESSION, compression.toInt());
205  qDebug("-------------------------");
206  qDebug("info:");
207  qDebug("compression = %d", af_compression);
208  qDebug("channels = %d", info.tracks());
209  qDebug("rate = %0.0f", info.rate());
210  qDebug("bits/sample = %d", info.bits());
211  qDebug("length = %lu samples",
212  static_cast<unsigned long int>(info.length()));
213  qDebug("format = %d (%s)", af_sample_format,
214  DBG(sample_format_name));
215  qDebug("-------------------------");
216 
217  // set up libaudiofile to produce Kwave's internal sample format
218 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
219  afSetVirtualByteOrder(fh, AF_DEFAULT_TRACK, AF_BYTEORDER_BIGENDIAN);
220 #else
221  afSetVirtualByteOrder(fh, AF_DEFAULT_TRACK, AF_BYTEORDER_LITTLEENDIAN);
222 #endif
223  afSetVirtualSampleFormat(fh, AF_DEFAULT_TRACK,
224  AF_SAMPFMT_TWOSCOMP, SAMPLE_STORAGE_BITS);
225 
226  return true;
227 }
228 
229 //***************************************************************************
230 bool Kwave::AudiofileDecoder::decode(QWidget */*widget*/,
231  Kwave::MultiWriter &dst)
232 {
233  Q_ASSERT(m_src_adapter);
234  Q_ASSERT(m_source);
235  if (!m_source) return false;
236  if (!m_src_adapter) return false;
237 
238  AFfilehandle fh = m_src_adapter->handle();
239  Q_ASSERT(fh);
240  if (!fh) return false;
241 
242  unsigned int frame_size = Kwave::toUint(
243  afGetVirtualFrameSize(fh, AF_DEFAULT_TRACK, 1));
244 
245  // allocate a buffer for input data
246  const unsigned int buffer_frames = (8 * 1024);
247  sample_storage_t *buffer =
248  static_cast<sample_storage_t *>(malloc(buffer_frames * frame_size));
249  Q_ASSERT(buffer);
250  if (!buffer) return false;
251 
252  // read in from the audiofile source
253  const unsigned int tracks = Kwave::FileInfo(metaData()).tracks();
255  while (rest) {
256  unsigned int frames = buffer_frames;
257  if (frames > rest) frames = Kwave::toUint(rest);
258  int buffer_used = afReadFrames(fh,
259  AF_DEFAULT_TRACK, reinterpret_cast<char *>(buffer), frames);
260 
261  // break if eof reached
262  if (buffer_used <= 0) break;
263  rest -= buffer_used;
264 
265  // split into the tracks
266  sample_storage_t *p = buffer;
267  unsigned int count = buffer_used;
268  while (count) {
269  for (unsigned int track = 0; track < tracks; track++) {
270  sample_storage_t s = *p++;
271 
272  // adjust precision
274  s /= (1 << (SAMPLE_STORAGE_BITS - SAMPLE_BITS));
275  }
276 
277  // the following cast is only necessary if
278  // sample_t is not equal to a quint32
279  *(dst[track]) << static_cast<sample_t>(s);
280  }
281  --count;
282  }
283 
284  // abort if the user pressed cancel
285  if (dst.isCanceled()) break;
286  }
287 
288  // return with a valid Signal, even if the user pressed cancel !
289  if (buffer) free(buffer);
290  return true;
291 }
292 
293 //***************************************************************************
295 {
296  if (m_src_adapter) delete m_src_adapter;
297  m_src_adapter = Q_NULLPTR;
298  m_source = Q_NULLPTR;
299 }
300 
301 //***************************************************************************
302 //***************************************************************************
AFfilehandle & handle()
static Kwave::Compression::Type fromAudiofile(int af_compression)
Definition: App.h:33
double rate() const
Definition: FileInfo.cpp:415
virtual Kwave::Decoder * instance() Q_DECL_OVERRIDE
QString description(IDX type, bool localized) const
Definition: TypesMap.h:128
virtual void close() Q_DECL_OVERRIDE
quint64 sample_index_t
Definition: Sample.h:28
virtual void open(Kwave::VirtualAudioFile *x, AFfilesetup setup)
void set(FileProperty key, const QVariant &value)
Definition: FileInfo.cpp:363
void setRate(double rate)
Definition: FileInfo.cpp:424
virtual void addMimeType(const char *name, const QString &description, const char *patterns)
Definition: CodecBase.cpp:47
static int error(QWidget *widget, QString message, QString caption=QString())
Definition: MessageBox.cpp:126
sample_index_t length() const
Definition: FileInfo.cpp:400
int toInt(T x)
Definition: Utils.h:127
void setLength(sample_index_t length)
Definition: FileInfo.cpp:409
void setTracks(unsigned int tracks)
Definition: FileInfo.cpp:454
virtual bool decode(QWidget *widget, Kwave::MultiWriter &dst) Q_DECL_OVERRIDE
qint32 sample_storage_t
Definition: Sample.h:40
virtual void replace(const MetaDataList &list)
virtual Kwave::MetaDataList & metaData()
Definition: Decoder.h:78
bool isCanceled() const
Definition: MultiWriter.h:64
virtual ~AudiofileDecoder() Q_DECL_OVERRIDE
unsigned int tracks() const
Definition: FileInfo.cpp:445
void setBits(unsigned int bits)
Definition: FileInfo.cpp:439
#define DBG(qs)
Definition: String.h:55
Kwave::VirtualAudioFile * m_src_adapter
#define SAMPLE_STORAGE_BITS
Definition: Sample.h:46
unsigned int toUint(T x)
Definition: Utils.h:109
unsigned int bits() const
Definition: FileInfo.cpp:430
#define SAMPLE_BITS
Definition: Sample.h:43
virtual bool open(QWidget *widget, QIODevice &source) Q_DECL_OVERRIDE
int toInt() const
Definition: Compression.h:122