当我从本机代码将非 nullptr 传递给 `alBufferData()` 时,OpenAL 应用程序崩溃/挂起

2024-04-19

我正在尝试使用 OpenAL 和 C/C++ 在 Android 上播放一些声音。我正在使用 SDL 框架。

我不断遇到神秘的崩溃alBufferData()即使我的代码很简单:

ALuint buf, src;
alGenBuffers(1, &buf);
alGenSources(1, &src);
uint8_t data[8000]{};
alBufferData(buf, AL_FORMAT_MONO8, data, 8000, 8000);
alSourcei(src, AL_BUFFER, buf);
alSourcePlay(src);

每次程序到达alBufferData()它崩溃或挂起。我没有收到任何类型的错误消息。

令人惊讶的是,如果我通过了0而不是实际的指针alBufferData(),那么程序运行良好并播放一些随机噪音。

我完全不知道出了什么问题。

MCVE:

#include <cstdlib>
#include <cmath>
#include <string>

#include <SDL2/SDL.h>
#include <AL/al.h>
#include <AL/alc.h>

#if !defined(ANDROID) && !defined(__ANDROID__)
#define GLEW_STATIC
#include <GL/glew.h>
#else
#include <GLES2/gl2.h>
#endif

void Msg(const char *txt)
{
    SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "test app", txt, 0);
}
void Err(const char *txt)
{
    Msg(txt);
    std::exit(0);
}

int SDL_main(int, char **)
{
    Msg("Running build compiled at " __DATE__ " " __TIME__);

    if (SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO))
        Err("SDL init failed");
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
    #if !defined(ANDROID) && !defined(__ANDROID__)
    SDL_Window *win = SDL_CreateWindow("test app", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
    #else
    SDL_Window *win = SDL_CreateWindow("test app", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_FULLSCREEN);
    #endif
    if (!win)
        Err("Window creation failed");
    SDL_GLContext con = SDL_GL_CreateContext(win);
    if (!con)
        Err("OpenGL context creation failed");
    #if !defined(ANDROID) && !defined(__ANDROID__)
    glewExperimental = 1;
    if (glewInit() != GLEW_OK)
        Msg("GLEW init failed");
    while (glGetError()) {}
    #endif
    SDL_GL_SetSwapInterval(1);

    ALCdevice *device = alcOpenDevice(0);
    if (!device)
        Err("OpenAL init failed");
    const ALCint config_array[] = {ALC_FREQUENCY, 44100, ALC_MONO_SOURCES, 4, ALC_STEREO_SOURCES, 4, 0};
    ALCcontext *context = alcCreateContext(device, config_array);
    if (!context)
        Err("OpenAL context creation failed");
    if (!alcMakeContextCurrent(context))
        Err("OpenAL context switching failed");


    uint8_t sound_wave[8000];
    for (int i = 0; i < 8000; i++)
    {
        float pi = std::atan(1)*4;
        sound_wave[i] = int(std::pow(std::sin(i * pi / 180 * 4),0.5) * 127) + 127;

        auto smoothstep = [](float x){return 2*x*x*x-3*x*x;};
        if (i < 1000)
            sound_wave[i] *= smoothstep(i / 1000.f);
        else if (i >= 7000)
            sound_wave[i] *= smoothstep((8000 - i) / 1000.f);
    }

    ALuint buf, src;
    int frames = 0;

    while (1)
    {
        SDL_Event event;
        bool click = 0;
        while (SDL_PollEvent(&event))
        {
            switch (event.type)
            {
              case SDL_QUIT:
                std::exit(0);
                break;
              case SDL_KEYDOWN:
                click = 1;
                break;
            }
        }

        switch (frames)
        {
          case 3:  Msg("Creating a buffer");   break;
          case 4:  alGenBuffers(1, &buf); if (!buf) Err("No buffer"); break;
          case 5:  Msg("Creating a source");   break;
          case 6:  alGenSources(1, &src); if (!src) Err("No source"); break;
          case 7:  Msg("Setting buffer data"); break;
          case 8:
            alBufferData(buf, AL_FORMAT_MONO8, sound_wave, 8000, 8000);
            if (int err = alGetError()) // This code is not reached
                Msg((std::string("Error code: ") + std::to_string(err)).c_str());
            break;
          case 9:  Msg("Attaching buffer");    break;
          case 10: alSourcei(src, AL_BUFFER, buf);  break;
          case 11: Msg("Done");                break;
        }
        if (frames < 12)
            frames++;

        if (frames == 12 && click)
            alSourcePlay(src);

        SDL_GL_SwapWindow(win);
    }
}

这是我的 Application.mk:

APP_ABI := armeabi armeabi-v7a x86 mips

APP_STL := c++_shared

LOCAL_SHARED_LIBRARIES := c++_shared
APP_CFLAGS += -w
APP_CPPFLAGS += -fexceptions -frtti -I../lib/include
APP_CPPFLAGS += -std=c++14 -O3 -s
NDK_TOOLCHAIN_VERSION := clang

我正在使用 OpenAL,它是使用独立工具链预先构建的。我不知道这是否重要,但这是我的构建命令(这个命令适用于armv7-a,对于其他ABI有不同的命令):

cmake -D CMAKE_SYSTEM_NAME:string=android -D CMAKE_C_COMPILER:filepath="Y:/clang_3.8_android_api12_androideabi/bin/arm-linux-androideabi-clang.cmd" ^
                                          -D CMAKE_CXX_COMPILER:filepath="Y:/clang_3.8_android_api12_androideabi/bin/arm-linux-androideabi-clang++.cmd" ^
                                          -D CMAKE_C_FLAGS:string="-w -O3 -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16" ^
                                          -D CMAKE_CXX_FLAGS:string="-w -O3 -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16" ^
                                          -D CMAKE_SHARED_LINKER_FLAGS:string="-lc++_shared" ^
                                          -D CMAKE_MODULE_LINKER_FLAGS:string="-lc++_shared" ^
                                          -D CMAKE_BUILD_TYPE:string="Release" ^
                                          -G "MinGW Makefiles" ^
                                          ../../..
mingw32-make.exe

EDIT:

现在它变得更有趣了。我已经设法让它工作一次,但是在对源代码进行了微小的无关更改之后,它再次崩溃了。

某处一定存在某种未定义的行为,但我确信它不站在我这边。

这是 OpenAL 中的错误吗?我使用的确切版本是openal-soft-1.17.1.

EDIT:

更新至 OpenAL 1.17.2。不走运,同样的错误。

EDIT:

以下是模拟器中 mcve 的 logcat 输出。 http://pastebin.com/428EsNa3
它是在外部托管的,因为它有 2000 多行长。

如果我理解正确的话,日志表明存在堆损坏,并且该应用程序已进行 sigsegv 处理dlmalloc()。但我不知道如何解决它。

我尝试添加SDL_INIT_AUDIO标记为SDL_Init()- 同样的错误。


你好:)对我来说这条线

alBufferData(buf, AL_FORMAT_MONO8, sound_wave, 8000, 8000);

应该是问题的一部分。 来自文档:

void alBufferData(
       ALuint      buffer,
       ALenum      format,
       const ALvoid *data,
       ALsizei      size,
       ALsizei      freq
      );

size :音频数据的大小(以字节为单位) freq :音频数据的频率

我的第一点是,您的频率 (8000) 可能不受实现支持,请尝试 44100 作为上下文频率。你需要扩大你的sound_wave大批。如果它有效,您可以通过对 5/6 样本使用相同的样本值来获得“8k”频率效果;)

我的第二点是对于尺寸,使用type可能会更好ALubyte from al.h并为size就像是sizeof(sound_wave) or samples_count * sizeof(ALubyte)确保并始终匹配代码更改。

但对于提供文件NULL代替data将设置AL_INVALID_VALUE错误状态(如alGetError()回报)

希望它会有所帮助

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当我从本机代码将非 nullptr 传递给 `alBufferData()` 时,OpenAL 应用程序崩溃/挂起 的相关文章

  • 如何使用 wpf webbrowser 将数据发布到 Web 服务器

    我想从数据库获取数据并使用它来让用户登录到网站 我有一个包含 Web 浏览器控件的 wpf 页面 我有这样的代码 用于将用户登录到用 php 编写的网站
  • 单线程公寓问题

    从我的主窗体中 我调用以下命令来打开一个新窗体 MyForm sth new MyForm sth show 一切都很好 但是这个表单有一个组合框 当我将其 AutoCompleteMode 切换为建议和追加时 我在显示表单时遇到了这个异常
  • 当创建 Android Jetpack Compose AndroidView 的参数发生变化时,如何替换它?

    我有一个应用程序 显示封装在其中的几个不同视图AndroidView 在下面重现的简单示例中 这些只是TextView实例 问题是更改文本 在本例中循环显示三个不同的值 似乎不会更新应用程序显示的内容 sealed class AppVie
  • 我可以仅在少数情况下关闭模拟吗

    我有一个始终使用模拟的应用程序 但是 当用户以管理员身份登录时 一些操作需要他们写入服务器本身 现在 如果这些用户在实际服务器上没有权限 有些用户没有 则不会让他们写入 我想做的是关闭几个命令的模拟 有没有办法做这样的事情 using Ho
  • 手动将 ClientBase 集合类型从 Array[] 更改为 List<>

    我将自己的 WCF 代理与 Client Base 一起使用 我想做一些类似于 svc util 中的 ct 属性的操作 并告诉代理返回 List 集合类型 我不能使用 List 因为实体由 nhibernate 管理 所以我必须使用 IL
  • 编译器错误“错误:在文件范围内可变地修改了‘字符串’”

    考虑 include
  • 防止GDB中的PLT(过程链接表)断点

    在最新版本的 GDB 中 在库函数调用上设置断点会导致多个实际断点 调用过程链接表 PLT 实际的函数调用 这意味着当调用库函数时 我们每次都会经历两次中断 在以前的 GDB 版本中 只会创建 2 因此您只能得到一次中断 那么问题来了 是否
  • C#中Enum中定义的value__是什么

    What value 可能在这里 value MSN ICQ YahooChat GoogleTalk 我运行的代码很简单 namespace EnumReflection enum Messengers MSN ICQ YahooChat
  • 允许使用什么类型的内容作为 C 预处理器宏的参数?

    老实说 我很了解 C 编程语言的语法 但对 C 预处理器的语法几乎一无所知 尽管我有时在编程实践中使用它 所以问题来了 假设我们有一个简单的宏 它扩展为空 define macro param 可以放入宏调用构造中的语法有哪些限制 调用宏时
  • 如何在Webview中保存用户名和密码

    目前 我还在学习Android开发的过程中 所以如果我的这个问题对你来说不太容易理解 请原谅 我创建了一个 Android 应用程序 它使用 RecyclerView 显示一组列表 当用户单击列表中的每个名称时 它会将它们重定向到一组不同的
  • Android - 保持用户登录状态

    我正在尝试使用 PHP 和 MySQLi for Android 进行登录 我不明白的是如何保持用户登录状态 我看到一个简单的教程 其中有人使用 SQLite 来保护信息 但我不知道这是否真的安全 如何保存用户信息以保持用户登录状态 谢谢
  • 不兼容的类型 - 是因为数组已经是指针吗?

    在下面的代码中 我创建一个基于书籍结构的对象 并让它保存多个 书籍 我设置的是一个数组 即定义 启动的对象 然而 每当我去测试我对指针的了解 实践有帮助 并尝试创建一个指向创建的对象的指针时 它都会给我错误 C Users Justin D
  • 使用(linq to sql)更新错误

    我有两个表 通过外键 CarrierID 绑定 Carrier CarrierID CarrierName CarrierID 1 CarrierName DHL CarrierID 2 CarrierName Fedex Vendor V
  • 使用 foreach 循环和 XmlNodeList C# 将新节点附加到节点列表

    目前我处理的是这样的XML类型 XML FILE http 20drive google com open id 0By5BxgNi9eGcRldxcEZNU0FDTzQ 参考XML文件 我想检查一个节点 如果找不到该节点 我必须将该节点附
  • 在 C++ 和 Windows 中使用 XmlRpc

    我需要在 Windows 平台上使用 C 中的 XmlRpc 尽管我的朋友向我保证 XmlRpc 是一种 广泛可用的标准技术 但可用的库并不多 事实上 我只找到一个库可以在 Windows 上执行此操作 另外一个库声称 您必须做很多工作才能
  • 动画结束后更改视图位置

    我开发了一个基于ViewGroup我的问题是我需要在动画结束后保存项目的位置 我打了电话setFillAfter true 在我创建的动画对象中AnimationListener并在其中onAnimationEnd方法调用View layo
  • 使用 Chrome 和 Selenium 设置 LocalStorage

    我正在尝试使用 OpenQA Selenium 和 Chrome 设置本地存储键和值 我认为这相当微不足道 但我似乎无法让它发挥作用 我对 C 很陌生 所以我可能错过了一些东西 无论如何 我有这个功能 public static void
  • 无法使 Polly 超时策略覆盖 HttpClient 默认超时

    我正在使用 Polly 重试策略 并且正如预期的那样 在重试过程中HttpClient达到 100 秒超时 我尝试了几种不同的方法来合并 Polly 超时策略 将超时移至每次重试而不是总计 但 100 秒超时仍然会触发 我读过大约 5 个
  • 同时有两个操作栏(底部和向上)?

    我需要制作两个操作栏 顺便说一下我正在使用actionBarSherlock 所以我真正需要的是在正常操作栏上放置一个 欢迎屏幕 开关 并添加两个正常的 ActionBar 操作选项 与我需要的类似的是 Gmail 和地图 如下所示 htt
  • 如何检测文本是否可读?

    我想知道是否有一种方法可以告诉给定的文本是人类可读的 我所说的人类可读的意思是 它有一些含义 格式就像某人写的文章 或者至少是由软件翻译器生成的供人类阅读的文章 这是背景故事 最近我正在制作一个应用程序 允许用户将短文本上传到数据库 在部署

随机推荐

  • 如何从 Ionic 选项卡打开 Ionic 模态

    我有一个用例 我想通过单击 Ion 选项卡来打开 Ionic Modal 我们的应用程序有 4 个固定的ion tabs 其中一个选项卡当前转到评论表单 但它更适合作为模式 因此用户可以快速完成表单并返回到他们正在做的事情 模态框通常附加到
  • Python CSV 编写器截断长数字

    我目前正在开发一个项目 该项目需要生成一个包含大量信息的 CSV 文件作为最终输出 目前 我将所有数据存储在一个非常大的列表中 然后使用 CSV 包将其写入 CSV 文件 我的问题是其中一个数据字段包含一个非常长的数字 存储为字符串 但第
  • Swift 栈和堆的理解

    我想快速了解堆栈和堆中存储的内容 我有一个粗略的估计 您打印的所有内容和内存地址都不是值 它们存储在堆栈中 而作为值打印出来的内容则在堆上 基本上根据值和引用类型 我完全错了吗 或者 您可以提供堆栈 堆的可视化表示吗 As Juul htt
  • 如何在 Firebase 实时数据库中保存本地数据?

    我对 Kotlin 和编程非常陌生 目前正在制作包含事件的日历 当我想将这些事件连接到 firebase 时 我的问题就出现了 我正在使用在 git 中找到的一个示例 https github com kizitonwose Calenda
  • 使用鼠标滚动 DataGridView

    因此 我们都熟悉单击并按住鼠标按钮 然后将鼠标移动到网格边缘 列 行滚动并且选择范围增加的功能 我有一个基于 DataGridView 的控件 由于性能问题 我必须关闭 MultiSelect 并自行处理选择过程 现在单击 按住滚动功能也被
  • 在matlab中对矩阵元素求和的有效(最快)方法

    让我们有矩阵A say A magic 100 我见过两种计算矩阵所有元素之和的方法A sumOfA sum sum A Or sumOfA sum A 其中一个比其他更快 或更好的练习 吗 如果有的话是哪一个 或者它们都同样快 看来你无法
  • 使用 PHPMailer 附加文​​件

    我有一个 HTML 表单 可以选择上传文件 然后 我想将该文件作为附件与其余表单数据一起发送到电子邮件地址 我正在使用 PHP Mailer 我获取要发送的表单数据 例如姓名 电话号码等 我无法将图像与它一起发送 我已经提供了迄今为止的代码
  • 如何在 Android 应用程序中播放和停止 mp3 文件

    我在 eclipse 中创建了一个应用程序来播放和停止 mp3 文件 一切都很好 除了当我播放音频文件并停止它并且我想重播它时 播放 btn 不起作用 我想知道是否有人可以帮助我 提前致谢 代码如下 package ir polyglotc
  • 更改 NUnit 测试的名称

    我希望我的单元测试基于NUnit在 Visual Studio 测试资源管理器中命名的框架更易于理解 例如 而不是有Test Case 1 or TestCase1我最好有类似的东西Test Case 1 Category First Ca
  • Android Room:应用与嵌入对象相关的多列

    在我的 Android 应用程序中 我使用 Room 进行数据存储 我目前面临的问题是 我需要在嵌入对象的 Relation 中放入 2 列 因为关系依赖于 2 列 结构见下图 Entity tableName damages public
  • 从通用平面获取轴对齐坐标

    标题可能是错误的 因为我不知道足够的数学知识来实际用一个小句子描述我的问题 我有一个 3D 矢量闭环 我将其称为 3D 多边形 我需要对其执行仅 2D 操作 这将返回一个 不同的 2D 点集 我需要将这些新的 2D 点转换回 3D 我目前的
  • 如何将下拉菜单置于父选项卡下居中?

    我有以下 CSS HTML 设置http jsfiddle net UDAUY http jsfiddle net UDAUY 如何对齐下拉菜单字段使其在父选项卡下居中 如下所示 MENU 1 MENU 2 MENU 3 MENU 4 Fi
  • 如何让 ko.compated 处理对象内的可观察值

    我有一个相当简单的视图模型来保存数据数组并获取一个我想用来过滤数据的字符串 我有一些非常简单的标记来渲染它 如下所示 section class task list ul li li ul section
  • 具有备用序列的列

    我想创建一个 user widgets 表 该表由 user id 和 user widget id 主键 其中 user widget id 的工作方式类似于序列号 除了每个用户从 1 个开始 对此有通用或实用的解决方案吗 我正在使用 P
  • networkx 通过属性搜索节点

    我寻找更优雅的方法来从以下属性之一搜索有向图中的节点 g nx DiGraph g add nodes from 1 dict d 0 a 7 2 dict d 0 a 6 g add nodes from 11 dict d 1 a 4
  • Android Studio - 非法字符 8204 错误

    由于某种原因 在重建我的项目后 我收到非法字符错误 但我的代码中没有任何内容以红色下划线显示 有人可以告诉我出了什么问题以及如何解决吗 Error illegal character 8204 WCBankActivity java imp
  • Linux 内核模块 Makefile 不能包含相对路径

    我正在尝试构建 Linux 内核模块 KBUILD EXTRA SYMBOLS Module symvers KBUILD EXTRA SYMBOLS dir0 Module symvers KDIR kernel linux 4 9 IN
  • Silverlight 中的计时器

    除了System Threading Timer对象之外 还有其他可以在Silverlight中使用的Timer对象吗 查看 DispatcherTimer http msdn microsoft com en us library sys
  • 在 SwiftUI 中正确使用 Task { }

    我想了解正确的用法Task 在以下 SwiftUI 代码中 我的目标是获得基本的了解以避免内存泄漏 这是 SwiftUI 部分的示例代码 struct MyView View ObservedObject var viewModel Vie
  • 当我从本机代码将非 nullptr 传递给 `alBufferData()` 时,OpenAL 应用程序崩溃/挂起

    我正在尝试使用 OpenAL 和 C C 在 Android 上播放一些声音 我正在使用 SDL 框架 我不断遇到神秘的崩溃alBufferData 即使我的代码很简单 ALuint buf src alGenBuffers 1 buf a