2

我正在尝试在可执行文件中播放 .mod 音频文件。我正在使用第 3 方 BASSMOD .dll。当我提供文件的完整路径时,我可以播放音频文件,但在提供相对路径时无法播放。这里有一些片段。

主文件

#include <QCoreApplication>
#include "bassmod.h"

// define file location
const char* file = "C:/Users/Downloads/test4/console/music.mod";

void startMusic() {
  BASSMOD_Init(-1, 44100, 0);
  BASSMOD_MusicLoad(FALSE,(void*)file,0,0,BASS_MUSIC_RAMPS);
  BASSMOD_MusicPlayEx(0,-1,TRUE);
}

int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  startMusic();
  return a.exec();
}

bassmod.h(相关片段)

BOOL BASSDEF(BASSMOD_MusicLoad)(BOOL mem, void* file, DWORD offset, DWORD length, DWORD flags);

我关心的功能是BASSMOD_MusicLoad. 就这个项目而言,.mod 文件播放没有问题。但是,当我尝试将 .mod 文件的绝对路径更改为相对路径(“music.mod”)时,文件无法播放。这是为什么?我在与可执行文件相同的目录以及包含 .pro 文件的目录中都有 .mod 文件——这似乎不是问题。

另外,也许我遗漏了一些与如何在 C++ 中打开文件有关的内容。看起来该MusicLoad函数要求第二个参数是 type void*。我敢肯定有很多不同的事情我可以在这里做得更好。理想情况下,我希望能够file存储 .mod 文件的相对路径并让它以这种方式播放,这样我就不必硬编码绝对路径。在一个完美的世界中,我想file在我的 resources.qrc 中提供一个 .mod 文件的路径,但是我必须使用QFile,我相信这不会起作用,因为我需要类型为 void*。

对初学者的任何帮助将不胜感激。


编辑01:谢谢大家的帮助!我让它工作(至少使用相对文件路径)。有两种方法可以做到这一点。这是我所做的以及我如何测试它:

第一种情况假设 BASSMOD(或您正在使用的任何外部 dll)不处理相对路径。

const char* file = "C:/debug/music.mod"; // same dir as .exe
QFileInfo info("music.mod");
QString path = info.absoluteFilePath();
const string& tmp = path.toStdString();
const char* raw = tmp.data();

这些是我设置的测试项目。当我运行时BASSMOD_MusicLoad(FALSE,(void*)file,0,0,BASS_MUSIC_RAMPS);,它按预期工作。那是我对完整的绝对路径进行硬编码的时候。

当我跑BASSMOD_MusicLoad(FALSE,(void*)raw,0,0,BASS_MUSIC_RAMPS);的时候,它没有用。所以我决定打印出所有东西的值,看看它在哪里搞砸了:

 cout << "Qstring path: ";
 qDebug() << path;
 cout << "string& tmp: ";
 cout << tmp << endl;
 cout << "raw: ";
 cout << raw << endl;
 cout << "full char* file: ";
 cout << file;
 startMusic();

...返回:

Qstring path:
"C:/myApp/build-Debug/music.mod"
string& tmp:
C:/myApp/build-Debug/music.mod
raw:
C:/myApp/build-Debug/music.mod
full char* file:
C:/myApp/build-Debug/debug/music.mod

注意区别?当我硬编码文件的完整路径时,我发现(感谢@FrankOsterfeld 和@JasonC)当前工作目录实际上不是 .exe (/debug) 或 .pro 文件所在的位置。它实际上与 Makefile 位于同一目录中。

所以我把它改成了这个:QFileInfo info("./debug/x.m");它工作了。

尽管问题最终是我不知道当前工作目录在哪里,@Radek、@SaZ 和 @JasonC 的解决方案帮助找到了另一种解决这个问题的方法(另外它向我展示了如何获取工作目录和转换类型之间)。对于想要使用 QFileInfo 来确定您在文件系统中的实际位置的人来说,这是一个很好的参考。如果我使用的 dll 不能很好地处理相对路径,我会使用这个解决方案。然而...

我想知道是否可以将相同的解决方案应用于我的原始代码(不使用 QFileInfo 和转换类型等)。我假设 BASSMOD 没有处理开箱即用的相对路径。我错了。我将file变量更改为const char* file = "./debug/x.m";它工作!

谢谢大家的帮助!

但是,我仍然希望使用 Qt 资源文件中的 music.mod 让它工作。但是,根据回复,除非您使用的第 3 方库支持 Qt 资源系统,否则这似乎是不可能的。

4

2 回答 2

4

我的 .mod 文件与可执行文件位于同一目录中。

在 Qt Creator 中,默认的初始工作目录是 .pro 文件所在的目录,而不是 .exe 最终所在的目录。

将您的文件放在该目录中(如果您使用典型设置,则可能包含所有源文件等的目录),或者将启动目录更改为 .exe 文件所在的目录(在运行设置区域)。

虽然,根据您在下面的新评论,我想问题比这更深......我无法真正告诉您为什么 BASS 不喜欢相对文件名,但您可以在将相对路径传递给之前将其转换为绝对路径低音。有很多方法可以做到这一点;使用 Qt 的 API,您可以:

#include <QFileInfo>

...
const char* file = "music.mod";  // Your relative path.
...

BASSMOD_MusicLoad(...,
                  (void*)QFileInfo(file).absoluteFilePath().toAscii().data(),
                  ...);

在一个完美的世界中,我想在我的 resources.qrc 中提供带有 .mod 文件路径的文件

您将无法这样做,因为从 .qrc 文件加载资源是 Qt 的事情,而 BASS 可能不会在内部使用 Qt(就像您无法使用 . 打开资源一样fopen),并且不了解如何加载资源由 Qt 嵌入。我对 BASS 不熟悉,但粗略地看一下这个文档表明它也有能力从内存缓冲区播放数据。因此,一种方法是使用 Qt 将资源加载到可访问的内存中并传递该缓冲区。

于 2016-01-28T05:07:21.483 回答
-1

在一个完美的世界中,我想在我的 resources.qrc 中提供带有 .mod 文件路径的文件,但是我相信我必须使用 QFile,因为我需要类型为 void *。

为什么你只相信?阅读 Qt 文档。它会起作用的。不要使用类QFile但是QFileInfo.

QFileInfo info(:/resourcePrefix/name);
QString path = info.absoluteFilePath();
void* rawPtr = (void*)path.toStdString().c_str();
于 2016-01-28T09:06:21.110 回答