void AudioItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *) { QMenu menu; QFont menuFont = qApp->font(); menuFont.setPixelSize(14); menu.setFont(menuFont); if (m_audio->getAudioDecoder() != NULL) { AudioDecoder *ad = m_audio->getAudioDecoder(); AudioParameters ap = ad->audioParameters(); if (ap.channels() == 1) m_previewLeftAction->setText(tr("Preview Mono")); menu.addAction(m_previewLeftAction); if (ap.channels() == 2) { m_previewLeftAction->setText(tr("Preview Left Channel")); menu.addAction(m_previewRightAction); menu.addAction(m_previewStereoAction); } menu.addSeparator(); } foreach(QAction *action, getDefaultActions()) menu.addAction(action); menu.exec(QCursor::pos()); }
void AudioEditor::slotSourceFileClicked() { QString fn; /* Create a file open dialog */ QFileDialog dialog(this); dialog.setWindowTitle(tr("Open Audio File")); dialog.setAcceptMode(QFileDialog::AcceptOpen); /* Append file filters to the dialog */ QStringList extList = Audio::getCapabilities(); QStringList filters; qDebug() << Q_FUNC_INFO << "Extensions: " << extList.join(" "); filters << tr("Audio Files (%1)").arg(extList.join(" ")); #if defined(WIN32) || defined(Q_OS_WIN) filters << tr("All Files (*.*)"); #else filters << tr("All Files (*)"); #endif dialog.setNameFilters(filters); /* Append useful URLs to the dialog */ QList <QUrl> sidebar; sidebar.append(QUrl::fromLocalFile(QDir::homePath())); sidebar.append(QUrl::fromLocalFile(QDir::rootPath())); dialog.setSidebarUrls(sidebar); /* Get file name */ if (dialog.exec() != QDialog::Accepted) return; fn = dialog.selectedFiles().first(); if (fn.isEmpty() == true) return; if (m_audio->isRunning()) m_audio->stopAndWait(); m_audio->setSourceFileName(fn); m_filenameLabel->setText(m_audio->getSourceFileName()); AudioDecoder *adec = m_audio->getAudioDecoder(); if (adec != NULL) { AudioParameters ap = adec->audioParameters(); m_durationLabel->setText(Function::speedToString(m_audio->getDuration())); m_srateLabel->setText(QString("%1 Hz").arg(ap.sampleRate())); m_channelsLabel->setText(QString("%1").arg(ap.channels())); m_bitrateLabel->setText(QString("%1 kb/s").arg(adec->bitrate())); } }
QVariant AudioEditor::mediaInfo() const { QVariantMap infoMap; if (m_audio == nullptr) return QVariant(); AudioDecoder *adec = m_audio->getAudioDecoder(); if (adec == nullptr) return QVariant(); AudioParameters ap = adec->audioParameters(); infoMap.insert("duration", Function::speedToString(m_audio->totalDuration())); infoMap.insert("sampleRate", QString("%1 Hz").arg(ap.sampleRate())); infoMap.insert("channels", ap.channels()); infoMap.insert("bitrate", QString("%1 kb/s").arg(adec->bitrate())); return QVariant::fromValue(infoMap); }
void AudioItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *) { QMenu menu; QFont menuFont = qApp->font(); menuFont.setPixelSize(14); menu.setFont(menuFont); if (m_audio->getAudioDecoder() != NULL) { AudioDecoder *ad = m_audio->getAudioDecoder(); AudioParameters ap = ad->audioParameters(); if (ap.channels() == 1) m_previewLeftAction->setText(tr("Preview Mono")); menu.addAction(m_previewLeftAction); if (ap.channels() == 2) { m_previewLeftAction->setText(tr("Preview Left Channel")); menu.addAction(m_previewRightAction); menu.addAction(m_previewStereoAction); } menu.addSeparator(); } menu.addAction(m_alignToCursor); if (isLocked()) { m_lockAction->setText(tr("Unlock item")); m_lockAction->setIcon(QIcon(":/unlock.png")); } else { m_lockAction->setText(tr("Lock item")); m_lockAction->setIcon(QIcon(":/lock.png")); } menu.addAction(m_lockAction); menu.exec(QCursor::pos()); }
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(); }
AudioEditor::AudioEditor(QWidget* parent, Audio *audio, Doc* doc) : QWidget(parent) , m_doc(doc) , m_audio(audio) , m_speedDials(NULL) { Q_ASSERT(doc != NULL); Q_ASSERT(audio != NULL); setupUi(this); m_nameEdit->setText(m_audio->name()); m_nameEdit->setSelection(0, m_nameEdit->text().length()); m_fadeInEdit->setText(Function::speedToString(audio->fadeInSpeed())); m_fadeOutEdit->setText(Function::speedToString(audio->fadeOutSpeed())); connect(m_nameEdit, SIGNAL(textEdited(const QString&)), this, SLOT(slotNameEdited(const QString&))); connect(m_fileButton, SIGNAL(clicked()), this, SLOT(slotSourceFileClicked())); connect(m_speedDialButton, SIGNAL(toggled(bool)), this, SLOT(slotSpeedDialToggle(bool))); connect(m_fadeInEdit, SIGNAL(returnPressed()), this, SLOT(slotFadeInEdited())); connect(m_fadeOutEdit, SIGNAL(returnPressed()), this, SLOT(slotFadeOutEdited())); connect(m_previewButton, SIGNAL(toggled(bool)), this, SLOT(slotPreviewToggled(bool))); AudioDecoder *adec = m_audio->getAudioDecoder(); m_filenameLabel->setText(m_audio->getSourceFileName()); if (adec != NULL) { AudioParameters ap = adec->audioParameters(); m_durationLabel->setText(Function::speedToString(m_audio->getDuration())); m_srateLabel->setText(QString("%1 Hz").arg(ap.sampleRate())); m_channelsLabel->setText(QString("%1").arg(ap.channels())); m_bitrateLabel->setText(QString("%1 kb/s").arg(adec->bitrate())); } QList<AudioDeviceInfo> devList; #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #if defined( __APPLE__) || defined(Q_OS_MAC) devList = AudioRendererPortAudio::getDevicesInfo(); #elif defined(WIN32) || defined(Q_OS_WIN) devList = AudioRendererWaveOut::getDevicesInfo(); #else devList = AudioRendererAlsa::getDevicesInfo(); #endif #else devList = AudioRendererQt::getDevicesInfo(); #endif QSettings settings; QString outputName; int i = 0, selIdx = 0; m_audioDevCombo->addItem(tr("Default device"), "__qlcplusdefault__"); if (m_audio->audioDevice().isEmpty()) { QVariant var = settings.value(SETTINGS_AUDIO_OUTPUT_DEVICE); if (var.isValid() == true) outputName = var.toString(); } else outputName = m_audio->audioDevice(); foreach( AudioDeviceInfo info, devList) { if (info.capabilities & AUDIO_CAP_OUTPUT) { m_audioDevCombo->addItem(info.deviceName, info.privateName); if (info.privateName == outputName) selIdx = i; i++; } } m_audioDevCombo->setCurrentIndex(selIdx); connect(m_audioDevCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(slotAudioDeviceChanged(int))); // Set focus to the editor m_nameEdit->setFocus(); }