00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qdatetime.h>
00022 #include <qprogressdialog.h>
00023
00024 #include <vorbis/vorbisfile.h>
00025
00026 #include "common.hh"
00027 #include "oggwave.hh"
00028
00029 OggWave::OggWave() : WaveFile()
00030 {
00031 ogg = new OggVorbis_File;
00032 }
00033
00034 OggWave::~OggWave()
00035 {
00036 }
00037
00038 bool OggWave::open(QString fname, int xres)
00039 {
00040 FILE *f;
00041 f = fopen(fname, "rb");
00042
00043 if(ov_open(f, ogg, NULL, 0) < 0)
00044 return false;
00045
00046 if(ov_seekable(ogg) == 0)
00047 return false;
00048
00049 if(ov_streams(ogg) != 1) {
00050
00051 }
00052 active_stream = 0;
00053
00054 channels = ov_info(ogg, active_stream)->channels;
00055 sampling = ov_info(ogg, active_stream)->rate;
00056
00057 loadWave();
00058 changeRes(xres);
00059
00060 opened = true;
00061 return true;
00062 }
00063
00064 void OggWave::close()
00065 {
00066 ov_clear(ogg);
00067 opened = false;
00068 }
00069
00070 QTime OggWave::length() const
00071 {
00072 return QTIME_MS((int)(1000.0 * ov_time_total(ogg, active_stream)));
00073 }
00074
00075 void OggWave::loadWave()
00076 {
00077 if(wave != NULL)
00078 delete[] wave;
00079
00080 char *packet = new char[PACKET_LENGTH * channels];
00081 size_t rate = (size_t)((double)sampling / MAX_PIXPERSEC) * channels;
00082 char *tmp = new char[rate];
00083 size_t tmppos = 0, bufpos = 0;
00084
00085 double const endtime = ov_time_total(ogg, active_stream);
00086 wavelength = (size_t)(endtime * MAX_PIXPERSEC * 2.0);
00087
00088 wave = new char[wavelength];
00089
00090 QProgressDialog progress(QObject::tr("Loading wave..."), 0, wavelength,
00091 0, "progress", TRUE);
00092
00093 ov_time_seek(ogg, 0);
00094 while(ov_time_tell(ogg) < endtime && bufpos <= wavelength - 2) {
00095 int curr;
00096 long i = 0;
00097 if((int)((double)bufpos / (double)wavelength * 1000.0) % 10 == 0)
00098 progress.setProgress(bufpos);
00099 long res = ov_read(ogg, packet, PACKET_LENGTH * channels, 0, 1, 1, &curr);
00100 while(i < res) {
00101 while(i < res && tmppos < rate)
00102 tmp[tmppos++] = packet[i++];
00103 if(tmppos == rate) {
00104 if(bufpos <= wavelength - 2) {
00105 char min = 0, max = 0;
00106 for(size_t j = 0; j < rate; ++j) {
00107 char const minmax = tmp[j];
00108 if(minmax < min)
00109 min = minmax;
00110 if(minmax > max)
00111 max = minmax;
00112 }
00113 wave[bufpos++] = min;
00114 wave[bufpos++] = max;
00115 }
00116 tmppos = 0;
00117 }
00118 }
00119 size_t newpos = ((size_t)(ov_time_tell(ogg) *
00120 MAX_PIXPERSEC * 2.0) / 2) * 2;
00121 if(newpos > bufpos && bufpos > 2)
00122 for(size_t j = bufpos; j < newpos; ++j)
00123 wave[j] = wave[j - 2];
00124 bufpos = newpos;
00125 }
00126 progress.setProgress(wavelength);
00127
00128 for(size_t i = bufpos; i < wavelength; ++i)
00129 wave[i] = 0;
00130
00131 delete[] tmp;
00132 delete[] packet;
00133
00134 }
00135
00136 void OggWave::waveFormat(WaveFormat &f) const
00137 {
00138 f.channels = channels;
00139 f.rate = (unsigned int)sampling;
00140 f.format = SND_PCM_FORMAT_S16_LE;
00141 f.access = SND_PCM_ACCESS_RW_INTERLEAVED;
00142 }
00143
00144 size_t OggWave::getPlayBufferSize(QTime const start, QTime const end) const
00145 {
00146 double const duration = (double)start.msecsTo(end) / 1000.0;
00147 return (size_t)(duration * (double)sampling) * channels * 2;
00148 }
00149
00150 void OggWave::getPlayBuffer(QTime const start, char *buf, size_t &size)
00151 {
00152 char *packet = new char[PACKET_LENGTH * channels];
00153 size_t bufpos = 0;
00154
00155 ov_time_seek(ogg, (double)MSECS(start) / 1000.0);
00156 while(bufpos < size) {
00157 int curr;
00158 long i = 0;
00159 long res = ov_read(ogg, packet, PACKET_LENGTH * channels, 0, 2, 1, &curr);
00160 if(res <= 0)
00161 break;
00162 while(i < res && bufpos < size)
00163 buf[bufpos++] = packet[i++];
00164 }
00165 if(size > bufpos)
00166 size = bufpos;
00167
00168 delete[] packet;
00169 }
00170