int AudioOpenAL::music_stream (ALuint buffer) { size_t size = music_decoder->read (music_data, setting.buffer); if (size > 0) { alBufferData (buffer, music_decoder->get_format (), music_data, size, music_decoder->get_frequency ()); } return size; }
void AudioItem::createWaveform(bool left, bool right) { if ((left == true || right == true) && m_audio->getAudioDecoder() != NULL) { AudioDecoder *ad = m_audio->getAudioDecoder(); AudioParameters ap = ad->audioParameters(); // 1- find out how many samples have to be represented on a single pixel on a 1:1 time scale int sampleSize = ap.sampleSize(); int channels = ap.channels(); int oneSecondSamples = ap.sampleRate() * channels; int onePixelSamples = oneSecondSamples / 50; //qint32 maxValue = qPow(0xFF, sampleSize); qint32 maxValue = 0; if (left == true && right == true) maxValue = 0x7F << (8 * (sampleSize - 1)); else maxValue = 0x3F << (8 * (sampleSize - 1)); quint32 defaultDataLen = onePixelSamples * sampleSize; // 2- decode the whole file and fill a QPixmap with a sample block RMS value for each pixel qint64 dataRead = 1; unsigned char audioData[defaultDataLen * 4]; quint32 audioDataOffset = 0; m_preview = new QPixmap((50 * m_audio->totalDuration()) / 1000, 76); m_preview->fill(Qt::transparent); QPainter p(m_preview); int xpos = 0; qDebug() << "Audio duration: " << m_audio->totalDuration() << ", pixmap width: " << ((50 * m_audio->totalDuration()) / 1000) << ", maxValue: " << maxValue; qDebug() << "Samples per second: " << oneSecondSamples << ", for one pixel: " << onePixelSamples; while (dataRead) { quint32 tmpExceedData = 0; if (audioDataOffset < defaultDataLen) { dataRead = ad->read((char *)audioData + audioDataOffset, defaultDataLen * 2); if (dataRead > 0) { if(dataRead + audioDataOffset >= defaultDataLen) { tmpExceedData = dataRead + audioDataOffset - defaultDataLen; dataRead = defaultDataLen; } else { audioDataOffset = dataRead; continue; } } } else { dataRead = defaultDataLen; tmpExceedData = audioDataOffset - defaultDataLen; } if (dataRead > 0) { quint32 i = 0; // calculate the RMS value (peak) for this data block double rmsLeft = 0; double rmsRight = 0; bool done = false; while (!done) { if (left == true) { qint32 sampleVal = getSample(audioData, &i, sampleSize); rmsLeft += (sampleVal * sampleVal); } if (channels == 2) { if (right == true) { qint32 sampleVal = getSample(audioData, &i, sampleSize); rmsRight += (sampleVal * sampleVal); } else getSample(audioData, &i, sampleSize); // got to read it anyway and discard data } if (i >= dataRead / sampleSize) done = true; } quint32 divisor = (dataRead / sampleSize) / channels; if (left == true) rmsLeft = sqrt(rmsLeft / divisor); if (right == true) rmsRight = sqrt(rmsRight / divisor); // 3- Draw the actual waveform unsigned short lineHeightLeft = 0, lineHeightRight = 0; if (left == true) lineHeightLeft = (76 * rmsLeft) / maxValue; if (right == true) lineHeightRight = (76 * rmsRight) / maxValue; if (left == true && right == true) { if (lineHeightLeft > 1) p.drawLine(xpos, 19 - (lineHeightLeft / 2), xpos, 19 + (lineHeightLeft / 2)); else p.drawLine(xpos, 19, xpos + 1, 19); if (lineHeightRight > 1) p.drawLine(xpos, 51 - (lineHeightRight / 2), xpos, 51 + (lineHeightRight / 2)); else p.drawLine(xpos, 51, xpos + 1, 51); } else { unsigned short lineHeight = 0; if (left == true) lineHeight = lineHeightLeft; else lineHeight = lineHeightRight; if (lineHeight > 1) p.drawLine(xpos, 38 - (lineHeight / 2), xpos, 38 + (lineHeight / 2)); else p.drawLine(xpos, 38, xpos + 1, 38); //qDebug() << "Data read: " << dataRead << ", rms: " << rms << ", line height: " << lineHeight << ", xpos = " << xpos; } xpos++; if (tmpExceedData > 0) { //qDebug() << "Exceed data found: " << tmpExceedData; memmove(audioData, audioData + defaultDataLen, tmpExceedData); audioDataOffset = tmpExceedData; } else audioDataOffset = 0; } } //qDebug() << "Iterations done: " << xpos; ad->seek(0); } else // no preview selected. Delete pixmap { delete m_preview; m_preview = NULL; } update(); }