wxPython和pycairo练习记录19

NVIDIA Jetson Xavier NX刷机教程 NVIDIA Jetson Xavier NX刷机教程,分别安装OS和SDK的经验分享 阅读详情

Sound.py 播放音频文件 https://github.com/mx0c/super-mario-python/blob/5623213c2eb001d8dabd95eb7035d7545e86ccf6/classes/Sound.py
在 wxPython 中 wx.adv.Sound 只能播放 WAV 格式的文件,或者在 UI 中调用 wx.media.MediaCtrl 控件,但素材里的音频还有 OGG 格式的,没法用 wxPython 在后台播放。

pygame.mixer.Sound 使用的是 Simple DirectMedia Layer (SDL) 提供的接口,详情见:
https://www.libsdl.org/index.php
https://github.com/libsdl-org/SDL
https://github.com/pygame/pygame/blob/main/src_c/cython/pygame/_sdl2/mixer.pxd
https://www.pygame.org/docs/ref/mixer.html

在 pygame 安装目录 python3\Lib\site-packages\pygame 中有 SDL2_mixer.dll,应该可以通过它调用并播放多种格式音频。另外还有个 libogg-0.dll,不考虑扩展,这个应该才是需要的。
使用工具查看 dll 导出函数:
https://github.com/lucasg/Dependencies/releases/tag/v1.11.1
dll导出函数

libogg-0.dll 提供了对 OGG 容器格式的基本支持,可以用来读取和处理 OGG 文件的数据结构。好像没什么用,它的作用有点像为现实里的鸡蛋编写一个鸡蛋类。

OGG 文件中保存的是压缩后的音频数据,而不是解码后的原始音频数据。解码是将压缩的音频数据转换为原始的 PCM 数据的过程,编码则相反。PCM(Pulse Code Modulation)脉冲编码调制,是一种将模拟信号转换为数字信号的方法。

这里的目标是读取 OGG 文件中的压缩数据,解码为 PCM 数据,转换为 WAV 格式数据,最后转为 wx.adv.Sound 对象。 WAV 数据就是 WAV 文件头加上 PCM 字节数据。

找到另一个库:
https://github.com/xiph/vorbis
编译好的 dll,libvorbisfile-3.dll 依赖 libogg-0.dll 和 libvorbis-0.dll,所以三个都需要:
https://github.com/QutEcoacoustics/audio-analysis/blob/master/lib/audio-utils/win-x64/sox/libvorbisfile-3.dll
https://github.com/QutEcoacoustics/audio-analysis/blob/master/lib/audio-utils/win-x64/sox/libogg-0.dll
https://github.com/QutEcoacoustics/audio-analysis/blob/master/lib/audio-utils/win-x64/sox/libvorbis-0.dll

# 此代码不能正常运行,提示 OSError: exception: access violation writing 0x0062F564
import ctypes

# 加载 libvorbisfile-3.dll
vorbisfile_lib = ctypes.CDLL("./classes/libvorbisfile-3.dll")

# 定义函数参数类型
vorbisfile_lib.ov_open_callbacks.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p), ctypes.c_char_p, ctypes.c_long, ctypes.c_void_p]
vorbisfile_lib.ov_open_callbacks.restype = ctypes.c_int

vorbisfile_lib.ov_read.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_char), ctypes.c_int, ctypes.POINTER(ctypes.c_int), ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_int)]
vorbisfile_lib.ov_read.restype = ctypes.c_int

# 打开 OGG 文件
ogg_file = "./sfx/coin.ogg"
ogg_file_handle = open(ogg_file, "rb")

# 创建 OggVorbis_File 结构体
ov_struct = ctypes.c_void_p()

# 打开 OGG 文件流
# https://xiph.org/vorbis/doc/vorbisfile/ov_open_callbacks.html
vorbisfile_lib.ov_open_callbacks(ogg_file_handle.fileno(), ctypes.byref(ov_struct), None, 0, None)

# 获取音频信息
info = vorbisfile_lib.ov_info(ctypes.byref(ov_struct), -1)
print(info)
# 读取和解码音频数据
pcm_data = b""
while True:
    pcm_temp = (ctypes.c_char * 4096)()  # 创建缓冲区数组
    ret = vorbisfile_lib.ov_read(ctypes.byref(ov_struct), pcm_temp, len(pcm_temp), None, 2, 1, None)
    if ret == 0:
        break
    pcm_data += pcm_temp.raw[:ret]

# 关闭 OGG 文件流
vorbisfile_lib.ov_clear(ctypes.byref(ov_struct))

# 关闭 OGG 文件
ogg_file_handle.close()

print(pcm_data)

不知道怎么解决这个上面代码的问题,只能先换个方法了。pip3 install pyogg ,它可以用于读取并解码 OGG。

wx.adv.Sound 并没有播放声道参数,只有标志位用于设置是同步还是异步播放。pygame.mixer.Channel 这里的声道和音频文件的声道含义不一样,这里的声道是指播放通道,0 为第一个声道。SFX(Sound Effects)指声音特效。原作者的意思应该是一个声道用于播放背景音乐,一个声道用于播放音效。

测试的时候,只有设置同步播放 wx.adv.SOUND_SYNC 才有声音,后面再修改,所有代码都完成了如果还是这样就再创建一个线程来播放声音。

# Sound.py
import struct
import pyogg
import wx.adv


class Sound:
    def __init__(self):
        self.allow_sfx = True

        self.soundtrack = self.load_ogg("../sfx/main_theme.ogg")
        self.coin = self.load_ogg("../sfx/coin.ogg")
        self.bump = self.load_ogg("../sfx/bump.ogg")
        self.stomp = self.load_ogg("../sfx/stomp.ogg")
        self.jump = self.load_ogg("../sfx/small_jump.ogg")
        self.death = wx.adv.Sound("../sfx/death.wav")
        self.kick = self.load_ogg("../sfx/kick.ogg")
        self.brick_bump = self.load_ogg("../sfx/brick-bump.ogg")
        self.powerup = self.load_ogg('../sfx/powerup.ogg')
        self.powerup_appear = self.load_ogg('../sfx/powerup_appears.ogg')
        self.pipe = self.load_ogg('../sfx/pipe.ogg')

    def play_sfx(self, sfx):
        if self.allow_sfx:
            sfx.Play(wx.adv.SOUND_ASYNC)

    def play_music(self, music):
        # 循环播放
        music.Play(wx.adv.SOUND_ASYNC | wx.adv.SOUND_LOOP)

    @staticmethod
    def pcm_to_wav(pcm_data, channels, frequency, bit_depth):
    	# channels 声道,1单声道 2立体声,frequency 采样率,bit_depth 样本位数,表示声音振幅,取值 8/16/24/32 越高质量越好
        # wav 文件头
        wav_header = struct.pack('<4sI4s4sIHHIIHH4sI', b'RIFF', 36 + len(pcm_data), b'WAVE', b'fmt ', 16, 1, channels,
                                 frequency, frequency * channels * bit_depth // 8, channels * bit_depth // 8, bit_depth,
                                 b'data', len(pcm_data))
        # 拼接 wav 文件头和 pcm 数据
        wav_data = wav_header + pcm_data
        return wav_data

    def load_ogg(self, file_path):
        ogg = pyogg.VorbisFile(file_path)
        wav_data = self.pcm_to_wav(ogg.buffer, ogg.channels, ogg.frequency, 16)
        sound = wx.adv.Sound()
        sound.CreateFromData(wav_data)
        return sound


if __name__ == "__main__":
    import wx
    app = wx.App()
    s = Sound()
    s.play_music(s.soundtrack)
    s.play_sfx(s.coin)

MATLAB三元相图实战:从数据准备到高级可视化技巧全解析 本文深入解析了如何使用MATLAB绘制专业的三元相图(ternary plot)。文章从数据归一化、范围映射等预处理技巧入手,详细介绍了散点图、等高线图、凸包计算等高级可视化方法,并提供了多数据集对比与出版级图表美化的实战指南,帮助科研与工程人员高效呈现复杂的三元数据关系。 阅读详情

相关推荐

从零搭建医疗化验单识别系统:深度学习+OCR实战教程(附数据集)

本文详细介绍了如何从零开始构建一个医疗化验单智能识别系统。通过融合深度学习和OCR技术,系统能够应对版式多样、内容专业的医疗单据,实现从文本检测、识别到关键信息结构化抽取的全流程。文章提供了数据集处理、模型选型、训练微调及工程化部署的实战指南,并分享了避坑经验与性能优化策略,为开发者解决医疗信息化痛点提供了完整的技术方案。

k9l0m1的博客 493

wxPython和pycairo练习记录10

一开始考虑不全面,后面写的时候就只有一个心思,烂代码,完成就好。代码创建控件实例是个痛苦的过程,因为做的基本都是重复的事,能用循环的最好写进循环,熟悉控件后推荐用 wxFromBuilder。

SmileBasic的博客 568

Winget安装失败:深入解析InternetOpenUrl()错误0x80072efd的根源与修复

本文深入解析了使用Winget时遇到的InternetOpenUrl()错误0x80072efd。该错误通常源于DNS解析失败、网络代理配置不当或系统安全策略冲突,导致无法连接软件源。文章提供了从刷新DNS、修改Hosts文件到配置代理等一套完整的诊断与修复方案,帮助开发者快速解决安装障碍,恢复Winget的正常使用。

weixin_29290259的博客 935

wxPython和pycairo练习记录2

因为要实现图像的显示和交互,今天添加两个基础的图像容器类。

SmileBasic的博客 971

如何利用MATLAB建立Lotka-Volterra模型及其改进模型

今天我们要说的就是利用MATLAB对常微分方程进行数值求解的实例应用-Lotka-Volterra模型及其改进模型。20世纪40年代,Lotka(1925)和Volterra(1926)奠定了种间竞争关系的理论基础,他们提出的种间竞争方程对现代生态学理论的发展有着重大影响。

Nick的博客 2万+

老服务器焕新记:在Dell R730上折腾Nvidia K80显卡的完整记录(含Anaconda环境配置)

本文详细记录了在Dell R730服务器上为Nvidia K80计算卡安装驱动、配置CUDA及Anaconda环境的完整过程。文章重点解决了老旧硬件与CentOS 7系统的兼容性问题,提供了从BIOS设置、驱动版本精准匹配到Python机器学习环境搭建的实战指南,旨在帮助读者低成本挖掘旧服务器的GPU计算潜力。

weixin_29197835的博客 504

wxPython和pycairo练习记录8

经过障碍物的编写,发现需要停止前进并重新梳理一下。1.新的检测项加入时,已经在向混乱发展。是时候用上封装变化的编程工具,用策略模式或状态模式重写。2.显示,在基类引入层级和优先级,不同层低层级先绘制,同层高优先级先绘制。3.范围的碰撞和本身的碰撞的作用顺序。还有像已经实现的碉堡,只有一个外层碰撞区域,如果要多加几层呢,最外层出现坦克,射速为1,再近一层射速为5,最近一层射速达到20。

SmileBasic的博客 387

C#教程

C# 教程 C# 是一个简单的、现代的、通用的、面向对象的编程语言,它是由微软(Microsoft)开发的。 本教程将告诉您基础的 C# 编程,同时将向您讲解 C# 编程语言相关的各种先进理念。 现在开始学习 C#! C# 在线工具 谁适合阅读本教程? 本教程有助于初学者理解基础的 C# 编程。在学习完本教程后,您将到达一个中级的 C# 编程水平。

zm1_1zm 1万+

wxPython和pycairo练习记录1

学习,分为学和习,学完了不练习,让大脑觉得不重要,会忘记。所以,我决定练习并记录 wxPython 和 pycairo 的代码编写,如果你也想试试请自行配置环境。wxPython官网:https://www.wxpython.org/pycairo官网:https://cairographics.org/pycairo/本机环境:WIN10因为没有相关完整项目经验,所以不能把全局都设计好,先从基本的迭代。...

SmileBasic的博客 283

一文读懂 AI 模型训练流程

AI模型训练流程可分为五个关键步骤:首先进行数据准备,包括收集、清洗、标注和增强数据;其次选择合适的模型架构并搭建神经网络;然后通过前向传播、损失计算和反向传播进行模型训练;接着用验证集评估模型性能,并调整超参数;最后在测试集上检验模型泛化能力。整个过程需要精心设计每个环节,才能获得性能优异的AI模型。

牧晨加油站 1483

网规第三版:第4章网络资源设备(完结)

第 4 章 网络资源设备 调整内容: 更新主流网络设备(交换机、路由器、防火墙)的技术参数与选型标准 增加国产化网络设备与信创产品的相关内容 精简已淘汰的设备类型与技术指标

鹿鸣天涯 268

wxPython和pycairo练习记录6

这次想要实现障碍物。

SmileBasic的博客 330

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

wxPython和pycairo练习记录3

现在的感觉像是学武功的人,对着一本秘籍瞎练,没有师父,也没有参照,不知对错。之前写的有很多混乱的地方,比如主 fps 对对象 fps 的作用,比如 MovieClip 对象 surface 的宽高及对继承方法 GetWidth 的影响,等等没有影响现有结果的地方。唯一检验的标准是,实现出想要的效果。这次想实现的是,在四个角生成敌方坦克,自动行驶,相互碰撞转向。...

SmileBasic的博客 354

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

wxPython和pycairo练习记录9

想要实现的效果是,同时按下多个方向,无论松开或按下其他键,总是响应剩余最近按下的键,这里直接用列表存储处在按下状态的按键代码。测试 wxPython 按下多个方向后松开最近按下的,之前保持按住的会失效。那就不能靠按键直接改变坐标,只改变速度方向,然后坐标的计算移动交给定时器刷新。射击按键行为也交给定时器,只改变状态,不执行操作。效果看起来还不错。之后可以看到,坦克和砖墙碰撞时的回弹问题也没有了。...

SmileBasic的博客 449

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

wxPython和pycairo练习记录17

按理说素材图片虽然是位图但因为是纯色,手动缩放显示都没问题,不知道为什么会这样,网上解释说是"Cairo 默认使用线性插值算法进行缩放操作,而线性插值会导致图像像素的颜色被平滑地混合,从而造成图像的模糊效果。不要当过程完美主义者,很容易自我攻击。素材中的 characters.gif,用 wx.Image 加载后,调用 GetAlpha 方法发现得到不正确的透明通道值,而且 HasAlpha 得到的结果是 False,因为没有正确解释透明通道数据,RGB 数据也错了,加载后整个图片都变成了粉色。

SmileBasic的博客 897

wxPython和pycairo练习记录13

之前虽然通过设置窗口样式去掉了标题栏,但是背景看起来还是有些碍眼。通过 SetTransparent 只能调整整体透明度,文字和背景都透明了。希望实现的效果是背景透明,而文字不透明。

SmileBasic的博客 560

wxPython和pycairo练习记录4

继续写碰撞检测。

SmileBasic的博客 306

wxPython和pycairo练习记录12

过年在家刷视频号直播时发现弹幕互动游戏,挺有意思的,刚好诠释了反射的用法。想要自己也做一个弹幕游戏,于是就有了这个基本的需求,先让弹幕滚动显示出来,直播时可以当作小挂件。

SmileBasic的博客 434

wxPython和pycairo练习记录11

了解事件机制是学习 wxPython 绕不过去的坎,结合各种资料和个人理解整理了一下,如果有问题请留言指出。

SmileBasic的博客 587

wxPython和pycairo练习记录14

继续之前的坦克游戏。碰撞检测技术像什么四叉树、凸包,看不懂啊,所以先从成熟的 pygame 框架里抠出几个能用到的。之前写坦克游戏并没有明确组合多个 Sprite 对象,还是先只考虑独立的 Sprite 吧。这样,需要用到和改写的方法只有 `collide_rect、collide_rect_ratio、collide_circle、collide_circle_ratio、collide_mask`。

SmileBasic的博客 263

wxPython和pycairo练习记录7

继续写障碍,选几个典型的来写。有个问题,有调用图片文件的类,每次生成新实例,都重新加载一次图片。应该把素材统一加载为全局变量,具体使用只需要引用素材变量。积重难返,记住这个教训,以后写其他的再注意吧。...

SmileBasic的博客 503

wxPython和pycairo练习记录15

像素:是指在由一个数字序列表示的图像中的一个最小单位,称为像素。这里的像素并非我们平时所说的眼睛看到的点,它更像是屏幕上的一个网格,不同的显示设备可能有不同大小的格子。在 Python 中,我们可以方便地通过一些库读取图像的某个像素值。这个例子中,返回的像素值是 RGBA 数值元组。

SmileBasic的博客 416

wxPython和pycairo练习记录5

先不管稀烂的坦克碰撞检测,开始添加武器系统。

SmileBasic的博客 232

wxPython和pycairo练习记录18

Font.py 中 Font 类居然继承 Spritesheet 类来加载字符对应图片,还和 Sprites 类的功能差不多,总感觉哪里不太对。基本都没法写测试啊,后面待完成的是声音、鼠标键盘输入、碰撞检测、实体和主要显示类:面板、关卡、菜单、暂停画面。Camera.py 摄像机,这里的功能是记录坐标,跟随实体移动坐标。

SmileBasic的博客 396

wxPython和pycairo练习记录16

先找出没有依赖其他文件的代码,可以作为后续其他代码的零件,这里选择 https://github.com/mx0c/super-mario-python/blob/master/classes/Spritesheet.py。总之,将图像存储在 Surface 中的主要目的是为了提供一个统一的、灵活的、可移植的绘图接口,使得开发者可以更容易地进行绘图操作,并且可以轻松地将相同的绘图操作应用于不同的输出目标。在 Cairo 中,一切都被视为绘图操作,即使是对图像的修改也被视为在绘图上下文中进行的操作。

SmileBasic的博客 380

windows上放弃使用PyGTK

windows上放弃使用PyGTK windows上放弃使用PyGTK - riag的专栏 - 博客频道 - youkuaiyun.com windows上放弃使用PyGTK 分类: python 2010-03-31 16:47 710人阅读 评...

106
上一篇: wxPython和pycairo练习记录18
下一篇: C语言学习记录
SmileBasic
博客等级 码龄5年 347粉丝 32原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值