创建分类音乐库的有效方法

时间:2019-03-30 14:16:34

标签: c++ qt sorting vector set

我正在尝试在qt / c ++中创建自己的音乐播放器/库。 我已经完成的工作是扫描文件夹中的音乐文件,使用 taglib 读取音乐文件的标签,从文件中创建Track结构,然后将{{1} } Track内。这是我到目前为止的代码:

这将扫描文件夹:

vector

然后在scanFile方法中进一步处理每个音频文件:

void LibraryScanner::scanFolder (std::string scanFolder) {
    if (filesystem::exists (scanFolder) && filesystem::is_directory (scanFolder))
    {
        filesystem::recursive_directory_iterator recursiveIterator (scanFolder);

        for (const auto& entry : filesystem::recursive_directory_iterator (scanFolder)) {
            std::wstring path = entry.path().wstring ();
            if (hasEnding (path, L".flac") || hasEnding (path, L".wav") || hasEnding (path, L".alac") || hasEnding (path, L".mp3") || hasEnding (path, L".m4a") || hasEnding (path, L".wma") || hasEnding (path, L".opus") || hasEnding (path, L".ogg") || hasEnding (path, L".aiff")) { ///TODO: ignore capital letters
                scanFile (path);
            }
        }
    }
}

每个轨道都放入此向量:

void LibraryScanner::scanFile (const std::wstring filePath)
{
    Track track = Track ();
    TagLib::FileRef f (filePath.c_str());
    if(!f.isNull()){
        track.filePath = filePath.c_str ();
        track.Title = f.tag()->title().toWString();
        track.Artists = f.tag()->artist().toWString();
        tracks.push_back (track);
    }else {
        std::wcout <<  "File is null." << '\n';
    }
}

这是std::vector<Track> tracks; 结构:

Track

所以现在,我希望音乐播放器像这样工作:

music player

sort

有一个按字母顺序排序的艺术家列表(图片左侧),每个艺术家都有不同的曲目(右侧),这些曲目也按其专辑排序。

我还应该注意,每个曲目可以有多个歌手,因此2位歌手可以共享同一曲目。

但是,我不仅可以按艺术家分类,还可以按专辑或其他标签分类(您可以在第二张图片中看到)。在此程序中,立即可以在按艺术家/专辑排序之间切换。

那么,如何在自己的程序中实现类似的功能(同样非常有效)? 我当时正在考虑在扫描过程中对所有内容进行预分类。因此,在将每个#pragma once #include<string> struct Track{ std::wstring filePath, Title, Artists; }; 放入轨道的Track中之后,我创建了vectorvector的艺术家,每个艺术家都包含轨道或唱片集。因此,我创建了一个Set结构,如下所示:

Artist

由于多个艺术家可以共享曲目,所以我认为使曲目矢量仅包含#pragma once #include <vector> #include "Track.h" #include <string> class Artist { public: Artist (std::wstring artistName); ~Artist (); std::wstring artistName; std::vector<Track*> tracks; }; 的指针是一个好主意。

所以我的艺术家列表是Track,每个艺术家都包含带有相同Artist标记的曲目(以后可以按专辑排序)。

然后,如果我想按专辑排序,我还有另一个像这样的向量:std::vector<Artist> artists;,每个std::vector<Album> albums;都包含自己的曲目。 而且,如果要切换排序模式,只需更改将哪个矢量显示为列表即可。

我的问题是,是否有一种更高效/高效的方法来完成所有这些工作。 看来这将占用大量内存,并且将花费大量时间进行排序,因为我基本上会在扫描后进行多次排序(对于每种排序模式,一个向量)。

此外,我需要检查是否有重复的歌手。另外,每个曲目/艺术家/专辑都应该有自己想要显示的封面图像。我也需要检查重复项

因此,这种方式将占用大量资源。 如果有人知道如何有效地执行此操作,并且可能也有一些代码示例,我将非常感激。 而且,如果有人知道一种更高效的方式来扫描文件夹中的文件或我在发布的代码段中所做的工作,那也将有所帮助。

谢谢!

2 个答案:

答案 0 :(得分:1)

使用数据库:  使用像mysql这样的数据库来存储所有音频信息和元数据。排序和重复检查将更容易实现。

分类音频文件:  根据类型将文件分类到单独的文件夹中。如果音频文件的数量很大,则排序后一次只能加载一个页面,然后进入后续页面。

在播放列表中使用smart_pointer:       使用std :: shared_ptr从媒体文件夹加载到播放列表。这将减少更多的内存消耗。例如,如果在音频文件之间插入了广告,则这两个部分可能仍具有相同的字段。

答案 1 :(得分:1)

您应该尝试研究模型视图控制器框架类,例如https://doc.qt.io/qt-5/model-view-programming.html

它们具有基于基于内存或文件系统或基于sqlite的数据的模型的代理模型的概念,并且这些代理模型具有诸如排序和过滤之类的功能。

创建GUi也是自动的,因为您只需要将列表视图或树形视图与代理模型连接即可。

这些是高度优化的模型,并且使用更少的代码也可以非常有效地进行排序和过滤。