00001 #include "debug.h"
00002 #include "input_speex.h"
00003
00004
00005 namespace audiere {
00006
00007 class FileReader : public speexfile::Reader {
00008 private:
00009 FilePtr m_file;
00010 bool m_seekable;
00011
00012 public:
00013 FileReader(FilePtr file) {
00014 m_file = file;
00015
00016
00017 m_seekable = m_file->seek(0, File::BEGIN);
00018 }
00019
00020 int read(void* ptr, int size) {
00021 return m_file->read(ptr, size);
00022 }
00023
00024 speexfile::offset_t seek(speexfile::offset_t offset) {
00025 m_file->seek(static_cast<int>(offset), File::BEGIN);
00026 return get_position();
00027 }
00028
00029 speexfile::offset_t get_position() {
00030 return m_file->tell();
00031 }
00032
00033 speexfile::offset_t get_length() {
00034 speexfile::offset_t c = get_position();
00035 m_file->seek(0, File::END);
00036 speexfile::offset_t l = get_position();
00037 m_file->seek(static_cast<int>(c), File::BEGIN);
00038 return l;
00039 }
00040
00041 bool can_seek() {
00042 return m_seekable;
00043 }
00044 };
00045
00046
00047 SpeexInputStream::SpeexInputStream() {
00048 m_speexfile = 0;
00049 m_position = 0;
00050 }
00051
00052
00053 SpeexInputStream::~SpeexInputStream() {
00054 delete m_speexfile;
00055 }
00056
00057
00059 bool
00060 SpeexInputStream::initialize(FilePtr file) {
00061 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00062 m_reader = std::auto_ptr<speexfile::Reader>(new FileReader(file));
00063 #else
00064 m_reader.reset(new FileReader(file));
00065 #endif
00066 m_speexfile = new speexfile::speexfile(m_reader.get());
00067
00068
00069 if (m_speexfile->get_streams() != 1) {
00070 delete m_speexfile;
00071 m_speexfile = 0;
00072 return false;
00073 }
00074
00075 speexfile::int32_t rate = m_speexfile->stream_get_samplerate();
00076 speexfile::int32_t channels = m_speexfile->stream_get_channels();
00077 if (rate == 0 || channels == 0) {
00078 delete m_speexfile;
00079 m_speexfile = 0;
00080 return false;
00081 }
00082
00083 for (int i = 0; i < m_speexfile->stream_get_tagcount(); ++i) {
00084 const speexfile::speextags* tag = m_speexfile->stream_get_tags()[i];
00085 addTag(
00086 tag->item ? tag->item : "",
00087 tag->value ? tag->value : "",
00088 "Speex");
00089 }
00090
00091 return true;
00092 }
00093
00094
00095 void
00096 SpeexInputStream::getFormat(
00097 int& channel_count,
00098 int& sample_rate,
00099 SampleFormat& sample_format)
00100 {
00101 channel_count = m_speexfile->stream_get_channels();
00102 sample_rate = m_speexfile->stream_get_samplerate();
00103 sample_format = SF_S16;
00104 }
00105
00106
00107 int
00108 SpeexInputStream::doRead(int frame_count, void* buffer) {
00109 s16* out = (s16*)buffer;
00110
00111 int total_read = 0;
00112 while (frame_count > 0) {
00113
00114 if (m_read_buffer.getSize() == 0) {
00115 float decode_buffer[2000];
00116 int speex_read = m_speexfile->decode(decode_buffer);
00117 if (speex_read == 0) {
00118 break;
00119 }
00120
00121 m_read_buffer.write(decode_buffer, speex_read * sizeof(float));
00122 }
00123
00124 const int BUFFER_SIZE = 1024;
00125 float read_buffer[BUFFER_SIZE];
00126
00127 int should_read = std::min(frame_count, BUFFER_SIZE);
00128 int actual_read = m_read_buffer.read(read_buffer, should_read * sizeof(float)) / sizeof(float);
00129 ADR_ASSERT(actual_read != 0, "Read queue should have data");
00130
00131 for (int i = 0; i < actual_read; ++i) {
00132 out[i] = s16(read_buffer[i] * 32767);
00133 }
00134
00135 frame_count -= actual_read;
00136 total_read += actual_read;
00137 out += actual_read;
00138 }
00139 m_position += total_read;
00140 return total_read;
00141 }
00142
00143
00144 void
00145 SpeexInputStream::reset() {
00146 setPosition(0);
00147 }
00148
00149
00150 bool
00151 SpeexInputStream::isSeekable() {
00152 return true;
00153 }
00154
00155
00156 int
00157 SpeexInputStream::getLength() {
00158 return static_cast<int>(m_speexfile->get_samples());
00159 }
00160
00161
00162 void
00163 SpeexInputStream::setPosition(int position) {
00164 m_speexfile->seek_sample(position);
00165 m_position = position;
00166 }
00167
00168
00169 int
00170 SpeexInputStream::getPosition() {
00171 return m_position;
00172 }
00173
00174 }