Redare fisiere u-law in qt
-
Salut, pentru a rula fisiere audio .raw poti folosi clasa "QAudioOutput":http://qt-project.org/doc/qt-5/qaudiooutput.html#details
-
Uite "aici":https://www.opensource.apple.com/source/tcl/tcl-87/tcl_ext/snack/snack/generic/g711.c gasesti implementare a conversiei ulaw (e si alaw, dar iei tu de acolo doar ce ai nevoie)
-
Nu m-am uitat prea atent, dar asa rapid nu am vazut numai functiile cu un parametru unsigned char sau short, deci ai nevoie de un loop si in el convertesti byte cu byte (sau cate doi bytes), sau iti scri tu loop-ul intr-o functie care ia pointer la date, marime si eventual pointer la un buffer prealocat pt rezultat (ca sa nu ai new intr-o parte si delete in alta parte)
Dar uita-te si tu atent ca poate mi-a scapat mie. -
Am incercat sa convertesc fisierele .raw insa desi nu apar erori nu se aude nimic. Stii cumva care ar putea fi problema? Multumesc
@
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{char mResourcePath[] ="/home/linux/records/opt2.raw"; for(int i = 0;i < 256;i++){ __ast_alaw[i] = ulaw2Lin(mResourcePath[i]); } const char* data; int size; QByteArray ba(data, size); for (int i = 0; i < sizeof(__ast_alaw); i++) { ba.append((const char*)(&__ast_alaw[i]), sizeof(__ast_alaw[i])); } QBuffer audio_buffer(&ba); audio_buffer.open(QIODevice::ReadOnly); qDebug() << audio_buffer.size(); QAudioFormat format; format.setSampleSize(8); format.setSampleRate(8000); format.setChannelCount(1); format.setCodec("audio/pcm"); format.setByteOrder(QAudioFormat::BigEndian); format.setSampleType(QAudioFormat::UnSignedInt); QAudioOutput output(format); output.start(&audio_buffer); // ...then wait for the sound to finish QEventLoop loop; QObject::connect(&output, SIGNAL(stateChanged(QAudio::State)), &loop, SLOT(quit())); do { loop.exec(); } while(output.state() == QAudio::ActiveState);//audio_buffer.size(); }
}
short Dialog::ulaw2Lin(unsigned char u_val)
{
short t;/* Complement to obtain normal u-law value. */ u_val = ~u_val; /* * Extract and bias the quantization bits. Then * shift up by the segment number and subtract out the bias. */ t = ((u_val & QUANT_MASK) << 3) + BIAS; t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}
@
-
Nu m-am uitat la tot codul, dar prima greseala e aici:
@ for(int i = 0;i < 256;i++){
__ast_alaw[i] = ulaw2Lin(mResourcePath[i]);
}@ in loc sa citesti din fisierul de la acel path, tu pasezi pe rand fiecare caracter al path-ului. Trebuie sa citesti datele din fisier, si datele din fisier sa le pasezi pe rand cate un byte functiei ulaw2lin.
Si mai trebuie sa ai grija cum aloci __ast_alaw (trebuie sa aloci acelasi numar ca si marimea datelor citite, dar din cate vad eu, trebuie sa fie de tipul short) -
Am reusit sa il fac sa functioneze. Singura problema e ca se aude un carait. Ai idee de ce se intampla asta?
@
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{char mResourcePath[] ="/home/dominic/testAudio/records/opt2.raw"; QFile audio_file(mResourcePath); if(audio_file.open(QIODevice::ReadOnly)) { QByteArray audio_data; QByteArray play; QBuffer audio_buffer(&play)
;
while (!audio_file.atEnd())
{audio_data = audio_file.read((qint64)160); int position = audio_file.pos(); int i = 0; for(i;i <= 160;i++){ __ast_alaw[i] = ulaw2Lin(audio_data[i]); qDebug() << i; play.append((const char*)(&__ast_alaw[i]), sizeof(__ast_alaw[i])); } } audio_file.close(); audio_buffer.open(QIODevice::ReadOnly); qDebug() << audio_buffer.size(); QAudioFormat format; format.setSampleSize(16); format.setSampleRate(8000); format.setChannelCount(1); format.setCodec("audio/pcm"); format.setByteOrder(QAudioFormat::LittleEndian); format.setSampleType(QAudioFormat::SignedInt); QAudioOutput output(info,format); output.start(&audio_buffer); // ...then wait for the sound to finish QEventLoop loop; QObject::connect(&output, SIGNAL(stateChanged(QAudio::State)), &loop, SLOT(quit())); do { loop.exec(); } while(output.state() == QAudio::ActiveState);//audio_buffer.size(); }
}
short Dialog::ulaw2Lin(unsigned char u_val)
{
short t;
u_val = ~u_val;
t = ((u_val & QUANT_MASK) << 3) + BIAS;
t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}
@ -
Eu am testat cu un fisier dar dupa ce am aplicat functia se aud doar distorsiuni (fara functie erau ceva distorsiuni dar se auzea si ce era in fisier) - dar e posibil ca fisierul sa nu fie mu-law, pt ca acel algoritm l-am gasit in mai multe locuri, deci pare sa fie bun, poti sa postezi un link catre un fisier ok (sau daca poti urca un fisier pe dropbox sau altundeva) si o sa testez si eu.
-
Salut. Am rezolvat problema. Modul corect de apelare este urmatorul:
@
QByteArray play;
if(audio_file.open(QIODevice::ReadOnly))
{
QByteArray audio_data;
{
audio_data = audio_file.read( audio_file.size() );for( int i = 0; i < audio_data.size(); ++i) { unsigned char tmp_data = audio_data[i]; short data = ulaw2Lin(tmp_data); play.append((const char*)&data, sizeof(short)); } } } audio_file.close();
@
Multumesc mult pentru ajutor!!!