/*! \file * implementation functions for class qwav */ #include # include "qwav.hh" # include "qexception.hh" #ifdef NLS # include # include # define _(s) gettext (s) #else # define _(s) (s) #endif u_int32_t qwav::append (qwav w) { if (!compatible(w)) throw qexception (__PRETTY_FUNCTION__, getName() + string(": ") + w.getName() + string(_(" is not compatible"))); qfile::append(w.getMap()+HEADERSIZE,w.getSize()-HEADERSIZE); remap(getMap()); addSamples(w.getSamples()); return getSamples(); } void qwav::print (ostream *os) { u_int32_t msduration; msduration = getMsDuration(); // cal posar les milčssimes? *os << getName() << ": " << getSampleRate() << " Hz " << getBitsPerSample() << " bits " << ((getChannels()==1)?"mono":"stereo") << ' '; os->width(2); *os << msduration/60000 << ':'; os->width(2); os->fill('0'); *os << (msduration/1000)%60 << '.'; os->width(2); os->fill('0'); *os << (msduration%1000)/10; /* os->form("%s: %u Hz %u bits %s %2u:%02u.%02u", getName().c_str(), getSampleRate(),getBitsPerSample(), ((getChannels()==1)?"mono":"stereo"), msduration/60000,(msduration/1000)%60,(msduration%1000)/10); */ } qwav::qwav(string name, u_int32_t flags) : qfile (name,flags), qwavheader(getMap(),getSize()) { } bool qwav::compatible (qwav &w) { return (getStereo() == w.getStereo()) && (getChannels() == w.getChannels()) && (getSampleRate() == w.getSampleRate()); } u_int32_t qwav::cut (u_int32_t firstsample, u_int32_t lastsample) { // s'hauria de comprovar la consistčncia dels parŕmetres... qfile::cut(getOffset(firstsample),getOffset(lastsample)+getBytesPerSample()-1); remap(getMap()); setSamples((getSize()-qwavheader::HEADERSIZE)/getBytesPerSample()); return getSamples(); } void qwav::move (u_int32_t sample_start, u_int32_t sample_end, u_int32_t sample_dest) { if (sample_endgetSamples()) { return; // ... } if (sample_end>getSamples()) { sample_end = getSamples(); // ... } // revisar d'ací en avall... u_int32_t sample_number = sample_end-sample_start; if (sample_number+sample_dest-1>getSamples()) { return; // ... } qfile::move(getOffset(sample_start), getOffset(sample_end)+getBytesPerSample()-1, getOffset(sample_dest)); } void qwav::truncate (u_int32_t samples) { if (samples>=getSamples()) return; qfile::truncate(HEADERSIZE+samples*getBytesPerSample()); remap(getMap()); setSamples(samples); } u_int32_t qwav::cut (qcuthandler &h) { if ((!h.getDel()) && (h.getOutfile()=="")) return 0; // // an schema with the cut specifications and what will be done // B => begin point, from the beginning of the file // E => end point, from the beginning of the file // b => begin point, from the end of the file // e => end point, from the end of the file // s => size of the fragment // // 0 means not specified 1 means specified // // B b E e s // 0 0 0 0 0 throw // 0 0 0 0 1 0 .. s // 0 0 0 1 0 0 .. e // 0 0 0 1 1 e-s .. e // 0 0 1 0 0 0 .. E // 0 0 1 0 1 E-s .. E // 0 0 1 1 0 throw // 0 0 1 1 1 throw // 0 1 0 0 0 b .. EOF // 0 1 0 0 1 b .. b+s // 0 1 0 1 0 b .. e // 0 1 0 1 1 throw // 0 1 1 0 0 b .. E // 0 1 1 0 1 throw // 0 1 1 1 0 throw // 0 1 1 1 1 throw // 1 0 0 0 0 B .. EOF // 1 0 0 0 1 B .. B+s // 1 0 0 1 0 B .. e // 1 0 0 1 1 throw // 1 0 1 0 0 B .. E // 1 0 1 0 1 throw // 1 0 1 1 0 throw // 1 0 1 1 1 throw // 1 1 0 0 0 throw // 1 1 0 0 1 throw // 1 1 0 1 0 throw // 1 1 0 1 1 throw // 1 1 1 0 0 throw // 1 1 1 0 1 throw // 1 1 1 1 0 throw // 1 1 1 1 1 throw // it is ugly, actually, but the table above should make things clear u_int32_t cutmode=0; if ( h.getBegin().getFormat()!=qvf::UNDEFINED ) cutmode+=16; if ( h.getbegin().getFormat()!=qvf::UNDEFINED ) cutmode+=8; if ( h.getEnd().getFormat()!=qvf::UNDEFINED ) cutmode+=4; if ( h.getend().getFormat()!=qvf::UNDEFINED ) cutmode+=2; if ( h.getSize().getFormat()!=qvf::UNDEFINED ) cutmode+=1; u_int32_t first_sample, last_sample; #ifdef QVERBOSE cerr << "cut mode: " << cutmode << endl; #endif // comprovació de zeros: -s 3b => -s 0!! switch (cutmode) { case 0: //cerr << "cut: you must specify where to cut" << endl; return 0; case 1: // 1 .. s (p) first_sample = 1; last_sample = getSample(h.getSize()); break; case 2: // 1 .. e (p) first_sample = 1; last_sample = getSamples()+1-getSample(h.getend()); break; case 3: // e-s .. e (p) last_sample = getSamples()+1-getSample(h.getend()); first_sample = last_sample-getSample(h.getSize())+1; break; case 4: // 1 .. E (p) first_sample = 1; last_sample = getSample(h.getEnd()); break; case 5: // E-s .. E (p) last_sample = getSample(h.getEnd()); first_sample = last_sample-getSample(h.getSize())+1; break; case 6: // E+e => throw (p) case 7: // E+e+s => throw (p) case 14: // b+E+e => throw (p) case 15: // b+E+e+s => throw (p) case 22: // B+E+e => throw (p) case 23: // B+E+e+s => throw (p) throw qexception(__PRETTY_FUNCTION__,string(_("options -E and -e cannot be used together"))); case 8: // b .. EOF (p) first_sample = getSamples()+1-getSample(h.getbegin()); last_sample = getSamples(); break; case 9: // b .. b+s (p) first_sample = getSamples()+1-getSample(h.getbegin()); last_sample = first_sample+getSample(h.getSize())-1; break; case 10: // b .. e (p) first_sample = getSamples()+1-getSample(h.getbegin()); last_sample = getSamples()+1-getSample(h.getend()); break; case 11: // b+e+s case 13: // b+E+s case 19: // B+e+s case 21: // B+E+s throw qexception(__PRETTY_FUNCTION__,string(_("options (-b or -B), (-e or -E) and -s cannot be used together"))); case 12: // b .. E (p) first_sample = getSamples()+1-getSample(h.getbegin()); last_sample = getSample(h.getEnd()); break; case 16: // B .. EOF (p) first_sample = getSample(h.getBegin()); last_sample = getSamples(); break; case 17: // B .. B+s (p) first_sample = getSample(h.getBegin()); last_sample = first_sample+getSample(h.getSize())-1; break; case 18: // B .. e (p) first_sample = getSample(h.getBegin()); last_sample = getSamples()+1-getSample(h.getend()); break; case 20: // B .. E first_sample = getSample(h.getBegin()); last_sample = getSample(h.getEnd()); break; case 24 ... 31: // B+b+... throw qexception(__PRETTY_FUNCTION__,string(_("options -B and -b cannot be used together"))); default: // this should never happen cerr << "quelcom panic!" << endl; return 0; } #ifdef QVERBOSE cerr << "cut: " << last_sample-first_sample+1 << " samples(" << first_sample << ".." << last_sample << ") => "; #endif if (first_sample>last_sample) throw qexception(__PRETTY_FUNCTION__, string(_("cut: last sample > first sample"))); // especificar quines mostres són if (last_sample>getSamples()) last_sample = getSamples(); if (h.getOutfile()!="") getWav(h.getOutfile(),first_sample,last_sample); if (h.getDel()) cut(first_sample,last_sample); return 1; } qwav& qwav::getWav(string name, u_int32_t startsample, u_int32_t endsample) { // s'ha de poder resoldre més elegantment...: un constructor nul de wav (nom de fitxer + parŕmetres i cap mostra) + un append qfile newwav(name,NEW); newwav.append(getMap(),qwavheader::HEADERSIZE); newwav.append(getMap()+getOffset(startsample),(endsample-startsample+1)*getBytesPerSample()); qwavheader h(newwav.getMap()); h.setSamples(endsample-startsample+1); // return ??? } ostream &operator<<(ostream &os, qwav &u) { u.print(&os); return os; }