void SpectrumAnalyserThread::calculateSpectrum(const QByteArray &buffer, int inputFrequency, int bytesPerSample, bool isSample,char phoneme) { #ifndef DISABLE_FFT //Q_ASSERT(buffer.size() == m_numSamples * bytesPerSample); // Initialize data array const char *ptr = buffer.constData(); for (int i=0; i<m_numSamples; ++i) { const qint16 pcmSample = *reinterpret_cast<const qint16*>(ptr); // Scale down to range [-1.0, 1.0] const DataType realSample = pcmToReal(pcmSample); const DataType windowedSample = realSample * m_window[i]; m_input[i] = windowedSample; ptr += bytesPerSample; } // Calculate the FFT m_fft->calculateFFT(m_output.data(), m_input.data()); // Analyze output to obtain amplitude and phase for each frequency FrequencySpectrum spectrum(SpectrumLengthSamples); if (isSample) { spectrum.setPhoneme(phoneme); } for (int i=2; i<=m_numSamples/2; ++i) { // Calculate frequency of this complex sample spectrum[i].frequency = qreal(i * inputFrequency) / (m_numSamples); const qreal real = m_output[i]; qreal imag = 0.0; if (i>0 && i<m_numSamples/2) imag = m_output[m_numSamples/2 + i]; const qreal magnitude = sqrt(real*real + imag*imag); qreal amplitude = SpectrumAnalyserMultiplier * log(magnitude); // Bound amplitude to [0.0, 1.0] spectrum[i].clipped = (amplitude > 1.0); amplitude = qMax(qreal(0.0), amplitude); amplitude = qMin(qreal(1.0), amplitude); spectrum[i].amplitude = amplitude; } #endif if (!isSample) { emit calculationComplete(spectrum); } else { emit sampleLoaded(spectrum); } }
//计算频谱 void SpectrumAnalyserThread::calculateSpectrum(const QByteArray &buffer, int inputFrequency, int bytesPerSample) { #ifndef DISABLE_FFT Q_ASSERT(buffer.size() == m_numSamples * bytesPerSample); // Initialize data array const char *ptr = buffer.constData(); for (int i=0; i<m_numSamples; ++i) { const qint16 pcmSample = *reinterpret_cast<const qint16*>(ptr); // Scale down to range [-1.0, 1.0] const DataType realSample = pcmToReal(pcmSample); const DataType windowedSample = realSample * m_window[i]; m_input[i] = windowedSample; ptr += bytesPerSample; } // Calculate the FFT快速傅里叶变换 m_fft ->calculateFFT(m_output.data(), m_input.data()); // Analyze output to obtain amplitude and phase for each frequency for (int i = 2; i <= m_numSamples / 2; ++i) { // Calculate frequency of this complex sample m_spectrum[i].frequency = double(i * inputFrequency) / (m_numSamples); const double real = m_output[i]; double imag = 0.0; if (i > 0 && i < m_numSamples / 2) { imag = m_output[m_numSamples / 2 + i]; } const double magnitude = sqrt(real * real + imag * imag); double amplitude = SpectrumAnalyserMultiplier * log(magnitude); // Bound amplitude to [0.0, 1.0] m_spectrum[i].clipped = (amplitude > 1.0); amplitude = qMax(double(0.0), amplitude); amplitude = qMin(double(1.0), amplitude); m_spectrum[i].amplitude = amplitude; } #endif emit calculationComplete(m_spectrum); //发射计算完成信号 }
void SpectrumAnalyserThread::calculateSpectrum(const QByteArray &buffer, int inputFrequency, int bytesPerSample) { Q_ASSERT(buffer.size() == m_numSamples * bytesPerSample); // Initialize data array const char *ptr = buffer.constData(); for (int i = 0; i < m_numSamples; ++i) { const qint16 pcmSample = *reinterpret_cast<const qint16*>(ptr); // Scale down to range [-1.0, 1.0] const DataType realSample = pcmToReal(pcmSample); const DataType windowedSample = realSample * m_window[i]; m_input[i] = windowedSample; m_cpxInput[i].re = windowedSample; m_cpxInput[i].im = 0.0f; ptr += bytesPerSample; } // Calculate the FFT m_fft->DoFFTWForward(m_cpxInput, m_cpxOutput, SpectrumLengthSamples); // Analyze output to obtain amplitude and phase for each frequency for (int i = 2; i <= m_numSamples / 2; ++i) { // Calculate frequency of this complex sample m_spectrum[i].frequency = qreal(i * inputFrequency) / (m_numSamples); //const qreal real = m_output[i]; const qreal real = m_cpxOutput[i].re; qreal imag = 0.0; if (i > 0 && i < m_numSamples / 2) //imag = m_output[m_numSamples/2 + i]; imag = m_cpxOutput[m_numSamples/2 + i].re; const qreal magnitude = sqrt(real*real + imag*imag); qreal amplitude = SpectrumAnalyserMultiplier * log(magnitude); // Bound amplitude to [0.0, 1.0] m_spectrum[i].clipped = (amplitude > 1.0); amplitude = qMax(qreal(0.0), amplitude); amplitude = qMin(qreal(1.0), amplitude); m_spectrum[i].amplitude = amplitude; } emit calculationComplete(m_spectrum); }
void Waveform::paintTile(int index) { const qint64 tileStart = m_tileArrayStart + index * m_tileLength; WAVEFORM_DEBUG << "Waveform::paintTile" << "index" << index << "bufferPosition" << m_bufferPosition << "bufferLength" << m_bufferLength << "start" << tileStart << "end" << tileStart + m_tileLength; Q_ASSERT(m_bufferPosition <= tileStart); Q_ASSERT(m_bufferPosition + m_bufferLength >= tileStart + m_tileLength); Tile &tile = m_tiles[index]; Q_ASSERT(!tile.painted); const qint16* base = reinterpret_cast<const qint16*>(m_buffer.constData()); const qint16* buffer = base + ((tileStart - m_bufferPosition) / 2); const int numSamples = m_tileLength / (2 * m_format.channelCount()); QPainter painter(tile.pixmap); painter.fillRect(tile.pixmap->rect(), Qt::black); QPen pen(Qt::white); painter.setPen(pen); // Calculate initial PCM value qint16 previousPcmValue = 0; if (buffer > base) previousPcmValue = *(buffer - m_format.channelCount()); // Calculate initial point const qreal previousRealValue = pcmToReal(previousPcmValue); const int originY = ((previousRealValue + 1.0) / 2) * m_pixmapSize.height(); const QPoint origin(0, originY); QLine line(origin, origin); for (int i=0; i<numSamples; ++i) { const qint16* ptr = buffer + i * m_format.channelCount(); const int offset = reinterpret_cast<const char*>(ptr) - m_buffer.constData(); Q_ASSERT(offset >= 0); Q_ASSERT(offset < m_bufferLength); Q_UNUSED(offset); const qint16 pcmValue = *ptr; const qreal realValue = pcmToReal(pcmValue); const int x = tilePixelOffset(i * 2 * m_format.channelCount()); const int y = ((realValue + 1.0) / 2) * m_pixmapSize.height(); line.setP2(QPoint(x, y)); painter.drawLine(line); line.setP1(line.p2()); } tile.painted = true; }
void SpectrumAnalyserThread::calculateTotalSpectrum(const QByteArray &buffer, int inputFrequency, int bytesPerSample) { if (m_spectrumList.count() > 0) m_spectrumList.clear(); int samples = bytesPerSample * m_numSamples; int buffers = qRound((float) buffer.size() / samples); // cycle over all buffers for (int i = 0; i < buffers; i++) { //if (i == buffers-1 && overhead > 0) m_tmp = QByteArray::fromRawData(buffer.constData() + i * samples, samples); //Q_ASSERT(m_tmp.size() == m_numSamples * bytesPerSample); // Initialize data array const char *ptr = m_tmp.constData(); for (int j = 0; j < m_numSamples; ++j) { const qint16 pcmSample = *reinterpret_cast<const qint16*>(ptr); // Scale down to range [-1.0, 1.0] const DataType realSample = pcmToReal(pcmSample); const DataType windowedSample = realSample * m_window[j]; m_cpxInput[j].re = windowedSample; m_cpxInput[j].im = 0.0f; ptr += bytesPerSample; } // calculate the FFT m_fft->DoFFTWForward(m_cpxInput, m_cpxOutput, SpectrumLengthSamples); /*for (int i = 0; i < BUFFER_SIZE; i += 32) { qDebug() << "m_cpxOutput.re =" << m_cpxOutput[i].re << "m_cpxOutput.im =" << m_cpxOutput[i].im; }*/ // Analyze output to obtain amplitude and phase for each frequency for (int i = 2; i <= m_numSamples / 2; ++i) { // Calculate frequency of this complex sample m_spectrum[i].frequency = qreal(i * inputFrequency) / (m_numSamples); //const qreal real = m_output[i]; const qreal real = m_cpxOutput[i].re; qreal imag = 0.0; if (i > 0 && i < m_numSamples / 2) imag = m_cpxOutput[m_numSamples/2 + i].re; const qreal magnitude = sqrt(real*real + imag*imag); qreal amplitude = SpectrumAnalyserMultiplier * log(magnitude); // Bound amplitude to [0.0, 1.0] m_spectrum[i].clipped = (amplitude > 1.0); amplitude = qMax(qreal(0.0), amplitude); amplitude = qMin(qreal(1.0), amplitude); m_spectrum[i].amplitude = amplitude; } m_spectrumList.append(m_spectrum); } emit calculationTotalComplete(m_spectrumList); }