QT music player
preface
Recently, I'm engaged in speech recognition. I didn't plan to make a music player. After reading the speech recognition chapter of punctual atom, I found that the music player seemed to be unable to get around. I also need to build a recording system behind it. If I don't agree, I'll do it. While the knowledge point is still hot, hurry to take notes and experience. Not much to say, showtime!!!
Work demonstration
The computer is not very awesome. There is a section that sounds like 2x speed. In fact, the code does not have this kind of situation. This is the pot of the screen recording software. My image of the great God will be destroyed once. Sobbing!
music player
Several key steps of code implementation
Step overview
1... Layout of ui files
2. Background pictures, including pictures of widget s and buttons
3. The progress bar is associated with music, and the playing time of the progress bar is displayed in real time
4. Display of lyrics
5. Display of song list and association of song list with songs
6. Repair some details
Layout of ui files
It's simple here, so I won't talk about it
Background pictures, including pictures of widget s and buttons
See the following figure for the background picture of the button:
In Find the button in the ui file - > right click to select "change style sheet" - > select "border image" in "add resource" - > select the image you added to the resource folder - > click Add
widget background image code:
QPixmap pix; pix.load(":/new/prefix1/background.jpg"); this->setAutoFillBackground(true); ///This line must be added QPalette bgPalette = this->palette(); bgPalette.setBrush(QPalette::Background,QBrush(pix)); this->setPalette(bgPalette);
The progress bar is associated with music, and the playing time of the progress bar is displayed in real time
Two slot functions used
connect(musicPlayer, SIGNAL(durationChanged(qint64)), this, SLOT(musicPlayerDurationChanged(qint64))); connect(musicPlayer,SIGNAL(positionChanged(qint64)),this,SLOT(onPositionChanged(qint64)));
The semaphore durationChanged is sent by musicPlayer. It will be triggered once at the beginning and end of the music. The parameter is the duration of the song.
The semaphore positionChanged is also sent by musicPlayer. It will be triggered when the music duration changes. The parameter is the duration of the song.
Knowing this, it is easy to associate the song with the progress bar.
ui->horizontalSlider->setMaximum(duration); //Set the maximum value of the progress bar, that is, the song duration (ms) int secs = duration/1000; //All seconds int mins = secs/60;//branch secs = secs % 60;//second durationTime = QString::asprintf("%d:%d",mins,secs);
We can get the duration of the song, ms level, assign the duration to the progress bar, and the total length of the progress bar will be
ui->horizontalSlider->setSliderPosition(position); int secs = position/1000; int mins = secs/60; secs = secs % 60; positionTime = QString::asprintf("%d:%d",mins,secs);
Assign the duration of the current song to the progress bar, which is equivalent to how long the song has been played and how far the progress bar has been drawn. The progress bar is cleverly linked with the song through the above code.
Display of lyrics
Before I came into contact with this experiment, I naively thought that the powerful QT would automatically get the songs in the songs and then analyze them. It only needed to call a few functions. Hahaha, what a beautiful thought. In fact, to display the lyrics, there must be a suffix of lvr file, open with Notepad is like this. You can know at a glance when to play which sentence. After we get such a file, we need to intercept it, including time and lyrics. Regular expressions are used. I downloaded the file from a netizen, and then used the CV method, hee hee hee. In order to express my gratitude, I will post his link later.
Let's take a look at the key code of this netizen. It looks a lot, but it's actually quite simple. The main codes used are QRegularExpression and QRegularExpressionMatch. The latter ones are to get the data, just to change the data type. Then store the data in Qlist.
bool Lyrices::analysisLyricsFile(QString line) { if(line == NULL || line.isEmpty()){ qDebug()<<"thie line is empty!"; return false; } QRegularExpression regularExpression("\\[(\\d+)?:(\\d+)?(\\.\\d+)?\\](.*)?"); QRegularExpressionMatch match; match = regularExpression.match(line); if(match.hasMatch()) { int totalTime; //Use regular expression to analyze it, and get it captured(1) .captured(2) .captured(3) .captured(4). . . Method acquisition totalTime = match.captured(1).toInt() * 60000 + match.captured(2).toInt() * 1000; /* Calculate the number of milliseconds at this time point */ QString currentText =QString::fromStdString(match.captured(4).toStdString()); /* Get lyrics text*/ listLyricsText.push_back(currentText); listLyricsTime.push_back(totalTime); } return false; }
After obtaining the lyrics and time, the next step is to display the lyrics in real time. It was said before that we can obtain how long the songs have been played. Then why can't we compare the data with the time data of the lyrics we obtained? However, the data of the lyrics is just larger than the time of the songs. Does it mean that the lyrics at that time point are to be displayed? The following function is the processing of the data obtained by the regular expression.
bool Lyrices::readLyricsFile(QString lyricsPath,qint64 what_ms) { QFile file(lyricsPath); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ listLyricsText.clear(); listLyricsTime.clear(); return false; } // The lyrics are obtained sentence by sentence, and then parsed and saved in the corresponding array by analysisLyricsFile QString line=""; while((line=file.readLine())>0){ analysisLyricsFile(line); } // Compare what we sent in_ Ms time parameter. If the number in the time array is just greater than the parameter we passed, the loop will be skipped for(int oo=0;oo<listLyricsTime.size();oo++) { if(what_ms<listLyricsTime[oo]) { currentTime_out=oo+1; break; } } return true; }
The parameters correspond to the path of the lyrics file to be parsed and the time point to be compared,
Explanation of the process: by opening the lyrics file of the path, clear the two qllists (listLyricsText, listLyricsTime) where the lyrics and time are saved, so as to avoid the data after the last parsing from interfering with the parsed data. Read the data of each line and save it to the line, and put it into the parsing function for parsing. After the parsing of the entire file is completed, use a for loop to compare, find the subscript that is longer than the song playing time, and return it, Use that subscript to find the lyrics we want.
The display of the song list and the association of the song list with the songs
Since one song and the lyrics can be corresponded normally, there is another problem, that is, we switch to another song, but the lyrics are still the lyrics we first analyzed. Therefore, the next problem we need to solve is that as the song changes, the lyrics should also correspond.
The display of the song list,
Most of the comments have been removed so as to make it less annoying,
Let me give you a brief explanation. Let's open a folder. The code shows that it is a music folder, and then define a filter to filter out files other than. Wav format, and filter the remaining files The wav file is saved in the QFileInfoList. The info here is a structure defined by me earlier. The elements in the structure include the name of the file and the directory of the file. Next, there are various transcoding operations. This is not the key. The key is a few lines of code in the if. Every time a song is imported into mediaPlaylist, the lyrics are imported into listwidget. So the subscript corresponds to.
For example, if we click the fifth line of listwidget, which is the fifth element of listwidget, and its current line is four, then we can find the song corresponding to the lyrics by looking up the fourth subscript of mediaPlaylist (starting from 0). After knowing this, it will be easy to operate later.
void Widget::scanning_file() { QDir dir("..//music"); QDir dirbsolutePath(dir.absolutePath()); /* If the directory exists: */ if (dirbsolutePath.exists()) { QStringList filter/* Define filters */ filter << "*.wav"; QFileInfoList files = dirbsolutePath.entryInfoList(filter, QDir::Files);/* Get all files in this directory */ for (int i = 0; i < files.count(); i++) { MediaObjectInfo info; /* Use utf-8 encoding */ QString fileName = QString::fromUtf8(files.at(i).fileName() .replace(".wav", "") .toUtf8() .data()); info.fileName = fileName+".\n"; info.filePath = QString::fromUtf8(files.at(i) .filePath() .toUtf8() .data()); /* Media list add songs */ if (mediaPlaylist->addMedia( QUrl::fromLocalFile(info.filePath))) { mediaObjectInfo.append(info);/* Add to container array for storage */ ui->listWidget->addItem(info.fileName); /* Add song name to list */ music_file_num++;//Gets the total number of files added to the list } } } }
Tinkering with some details
1. Pay special attention to logic issues. For example, our song is played normally. After playing, it will enter the next song by itself, and everything is normal; However, if I jump to another song through listwidget before the play is finished, he will still jump to the next song. This leads to the situation that if the song is not finished, I click Next and it will play the next song for me.
2. Prevent overflow. For example, when I play the last song, you still press the button of next song, which makes it find the next song. If it can't find it, it will report overflow. We need to deal with it and point to the first song again; The first song is the same as the first song
3. When the lyrics are displayed, we should make it push from the bottom to the top, or the first sentence of the lyrics spread from the middle to the top and bottom, to prevent the overflow of QList.
crap
The following routine code is provided for you. The relative paths are used and can be used directly. If you want to add additional songs, you should put the songs and lyrics files under the music folder. The song files and lyrics files should have the same name. Welcome to download. Here are some treasure sites for you. The pictures of the buttons we use are as follows icon format, which can be downloaded for free from below; The lyrics file also needs to be downloaded by ourselves. The songs we usually download are not included lvr file; Since I will migrate to imx6ull later, the board has not finished the mplayer yet, so I only play it here For wav format, we can obtain lossless music through the following website, convert it to WAV format through kugou (remember that mp3 is lossy and does not support conversion), or download wav format directly from that website, that is, there are fewer songs.
Some treasure sites
Icon icon download
lvr lyrics download
Lossless music download
Download the source code without any modification
Congratulations, this handsome man. I'd like to mention a little red flower
Congratulations, this pretty boy. I'm happy to bring a little red flower