수요일, 11월 20, 2019

QT wave file play


인터넷에서 찾으면 .. 나온다.. 라고 하면 글쓴 이유가 없지..

 일단 인터넷에서 찾아 볼 수 있는 흔한 예제...

QFile audio_file(strFullFilePath);
if(audio_file.open(QIDevice::ReadOnly)){
  audio_file.seek(44); // skip wav header
  QByteArray audio_data = audio_file.readAll();
  audio_file.close();

  QBuffer* audio_buffer = new QBuffer(&audio_data);
  
  QAudioFormat  format;

  format.setSampleSize(16);
  format.setSampleRate(44100);
  format.setChannelCount(2);
  format.setCodec("audio/pcm");
  format.setByteOrder(QAudioFormat::LittleEndian);
  format.setSampleType(QAudioFormat::UnsignedInt);

  QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
  if(!info.isFormatSupperted(format)) {      
      return; // Not support format
  }
  
  QAudioOutput* output = new QAudioOutput(info, format);
  output->start(audio_buffer);
}

간결하다. 근데 막상 테스트 해보면.. 안노온다.. 왜일까?

 우선.. output->start(audio_buffer)를 실행하는동안 내 Process는 살아 있어야 한다. 그렇기 때문에 간단히 맨 아래에 5줄 추가

 QEventLoop loop;
 QObject::connect(&output, SIGNAL(stateChanged(QAudio::State)), &loop, SLOT(quit()));
 do {
     loop.exec();
 } while(output.state() == QAudio::ActiveState);


일단 소리는 나온다. 하지만 이쁘게 나오는 경우도 있고 그렇지 않은 경우(도날드덕 목서리 내지는 테이프 빨리 감는소리)도 발생한다.  이 경우에는  약간의 대공사(?)를 진행하여 아래와 같은 코드가 필요하게 된다.

 QFile audio_file(FileName);
 QByteArray audio_Buffer;
 int Channels = 0;      // count of channel
 int SampleRate = 0;    // wave sampling rate
 int BPS = 0;           // Sample Size
 if(audio_file.open(QIODevice::ReadOnly)){
     char stream[4] = {0,};
     audio_file.read(stream, 4); //  Same with "RIFF"   not use
     audio_file.read(stream, 4); //  Chumk size         not use
     audio_file.read(stream, 4); //  Format             not use
     audio_file.read(stream, 4); //  Sub chunk1 ID      not use
     audio_file.read(stream, 4); //  Sub chunk1 size    not use
     audio_file.read(stream, 2); //  Audio Format       not use
     memset(stream,0, 4);
     audio_file.read(stream, 2); //  Channel number    use
     Channels = qFromLittleEndian<quint16>((uchar*)stream);
     memset(stream,0, 4);
     audio_file.read(stream, 4); //  Sample rate       use
     SampleRate = qFromLittleEndian<quint32>((uchar*)stream);
     audio_file.read(stream, 4); //  Byte rate         not use
     audio_file.read(stream, 2); //  Byte Allign       not use(아마도 엔디언 설정인듯)
     memset(stream,0, 4);
     audio_file.read(stream, 2); //  BPS               use
     BPS = qFromLittleEndian<quint16>((uchar*)stream);
     audio_file.read(stream, 4); //  Sub chunk2 ID      not use
     audio_file.read(stream, 4); //  Sub chunk2 size    not use
     audio_Buffer.clear();
     while(!file.atEnd())
     {
         char s[1];
         audio_file.read(s,1);
         audio_Buffer.append(s[0]);
     }
     audio_file.close();
     QBuffer audio_buffer(&audio_Buffer);
     audio_buffer.open(QIODevice::ReadOnly);
     QAudioFormat format;
     format.setSampleSize(BPS);
     format.setSampleRate(SampleRate);
     format.setChannelCount(Channels);
     format.setCodec("audio/pcm");
     format.setByteOrder(QAudioFormat::LittleEndian);
     format.setSampleType(QAudioFormat::UnSignedInt);
     QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
     if (!info.isFormatSupported(format)) {
         qWarning()<<"raw audio format not supported by backend, cannot play audio.";
         return;
     }
     // Create the device and start playing...
     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);
  }

완벽한 코드는 아니지만, 적어도 웨이브 파일 하나 정도는 잘 나오는 코드인듯 싶다.

댓글 없음: