xoreos  0.0.5
aac.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include <cstring>
26 
27 #include <neaacdec.h>
28 
29 #include <boost/scoped_array.hpp>
30 
31 #include "src/common/scopedptr.h"
33 #include "src/common/error.h"
35 
36 #include "src/sound/audiostream.h"
37 
38 #include "src/sound/decoders/aac.h"
39 #include "src/sound/decoders/pcm.h"
40 
41 namespace Sound {
42 
44 public:
46  ~AACDecoder();
47 
48  // AudioStream API
49  int getChannels() const { return _channels; }
50  int getRate() const { return _rate; }
51  bool endOfData() const { return _audStream->endOfData(); }
52  bool endOfStream() const { return _audStream->endOfStream(); }
53  size_t readBuffer(int16 *buffer, const size_t numSamples) { return _audStream->readBuffer(buffer, numSamples); }
54 
55  // PacketizedAudioStream API
56  void finish() { _audStream->finish(); }
57  bool isFinished() const { return _audStream->isFinished(); }
59 
60 private:
61  NeAACDecHandle _handle;
63  unsigned long _rate;
64 
65  // Backing stream for PacketizedAudioStream
67 
69 };
70 
72  // Open the library
73  _handle = NeAACDecOpen();
74 
75  // Configure the library to our needs
76  NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(_handle);
77  conf->outputFormat = FAAD_FMT_16BIT; // We only support 16bit audio
78  conf->downMatrix = 1; // Convert from 5.1 to stereo if required
79  NeAACDecSetConfiguration(_handle, conf);
80 
81  // Copy the extra data to a buffer
82  extraData.seek(0);
83  Common::ScopedArray<byte> extraDataBuf(new byte[extraData.size()]);
84  extraData.read(extraDataBuf.get(), extraData.size());
85 
86  // Initialize with our extra data
87  // NOTE: This code assumes the extra data is coming from an MPEG-4 file!
88  int err = NeAACDecInit2(_handle, extraDataBuf.get(), extraData.size(), &_rate, &_channels);
89  if (err < 0) {
90  NeAACDecClose(_handle);
91 
92  throw Common::Exception("Could not initialize AAC decoder: %s", NeAACDecGetErrorMessage(err));
93  }
94 
96 }
97 
99  NeAACDecClose(_handle);
100 }
101 
103  // read everything into a buffer
104  size_t inBufferPos = 0;
105  size_t inBufferSize = stream.size();
106 
107  boost::scoped_array<byte> inBuffer(new byte[inBufferSize]);
108  if (stream.read(inBuffer.get(), inBufferSize) != inBufferSize)
110 
112 
113  // Decode until we have enough samples (or there's no more left)
114  while (inBufferPos < inBufferSize) {
115  NeAACDecFrameInfo frameInfo;
116  void *decodedSamples = NeAACDecDecode(_handle, &frameInfo, inBuffer.get() + inBufferPos, inBufferSize - inBufferPos);
117 
118  if (frameInfo.error != 0)
119  throw Common::Exception("Failed to decode AAC frame: %s", NeAACDecGetErrorMessage(frameInfo.error));
120 
121  byte *buffer = new byte[frameInfo.samples * 2];
122  std::memcpy(buffer, decodedSamples, frameInfo.samples * 2);
123 
124  static const byte flags = FLAG_16BITS | FLAG_NATIVE_ENDIAN;
125 
126  audioStream->queueAudioStream(makePCMStream(new Common::MemoryReadStream(buffer, frameInfo.samples * 2, true), _rate, flags, _channels, true), true);
127 
128  inBufferPos += frameInfo.bytesconsumed;
129  }
130 
131  audioStream->finish();
132  return audioStream;
133 }
134 
137  _audStream->queueAudioStream(decodeFrame(*data));
138 }
139 
141  return new AACDecoder(extraData);
142 }
143 
144 } // End of namespace Sound
QueuingAudioStream * makeQueuingAudioStream(int rate, int channels)
Factory function for an QueuingAudioStream.
void finish()
Mark this stream as finished.
Definition: aac.cpp:56
PacketizedAudioStream * makeAACStream(Common::SeekableReadStream &extraData)
Create a PacketizedAudioStream that decodes AAC sound.
Definition: aac.cpp:140
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
NeAACDecHandle _handle
Definition: aac.cpp:61
virtual void finish()=0
Mark this stream as finished.
Implementing the reading stream interfaces for plain memory blocks.
bool isFinished() const
Is the stream marked as finished?
Definition: aac.cpp:57
RewindableAudioStream * makePCMStream(Common::SeekableReadStream *stream, int rate, byte flags, int channels, bool disposeAfterUse)
Creates an audio stream, which plays from the given stream.
Definition: pcm.cpp:140
Decoding PCM (Pulse Code Modulation).
int16_t int16
Definition: types.h:201
A simple scoped smart pointer template.
bool endOfStream() const
End of stream reached? If this returns true, it means that all data in this stream is used up and no ...
Definition: aac.cpp:52
virtual void queueAudioStream(AudioStream *audStream, bool disposeAfterUse=true)=0
Queue an audio stream for playback.
Definition: game.h:37
Basic exceptions to throw.
Common::ScopedPtr< QueuingAudioStream > _audStream
Definition: aac.cpp:66
An AudioStream designed to work in terms of packets.
Definition: audiostream.h:271
virtual size_t read(void *dataPtr, size_t dataSize)=0
Read data from the stream.
Simple memory based &#39;stream&#39;, which implements the ReadStream interface for a plain memory block...
Definition: memreadstream.h:66
AudioStream * decodeFrame(Common::SeekableReadStream &stream)
Definition: aac.cpp:102
bool endOfData() const
End of data reached? If this returns true, it means that at this time there is no data available in t...
Definition: aac.cpp:51
StackException Exception
Definition: error.h:59
const Exception kReadError("Read error")
Exception when reading from a stream failed.
Definition: error.h:62
Decoding AAC.
A scoped plain pointer, allowing pointer-y access and normal deletion.
Definition: scopedptr.h:120
virtual size_t size() const =0
Obtains the total size of the stream, measured in bytes.
void queuePacket(Common::SeekableReadStream *data)
Queue the next packet to be decoded.
Definition: aac.cpp:135
sound is 16 bits wide (default: 8bit)
Definition: pcm.h:72
Generic audio input stream.
Definition: audiostream.h:70
int getRate() const
Sample rate of the stream.
Definition: aac.cpp:50
A smart pointer with a deletion flag.
samples are in native endianness
Definition: pcm.h:81
byte _channels
Definition: aac.cpp:62
size_t readBuffer(int16 *buffer, const size_t numSamples)
Fill the given buffer with up to numSamples samples.
Definition: aac.cpp:53
unsigned long _rate
Definition: aac.cpp:63
int getChannels() const
Return the number channels in this stream.
Definition: aac.cpp:49
Interface for a seekable & readable data stream.
Definition: readstream.h:265
Streaming audio.
uint8 byte
Definition: types.h:209
AACDecoder(Common::SeekableReadStream &stream)
Definition: aac.cpp:71