从样本中提取频率的 Microsoft WAV
2014-1-6 0:16:43
收藏:0
阅读:105
评论:1
好的,所以我正在尝试在 Lua 中播放 WAV 文件。我已经了解到了一些信息,但是我卡在了实际播放歌曲上。我正在使用的函数是 Speaker.start(Channel, Frequency)。我从未使用过这样的东西来自一个原始文件中的 Lua,并且我不知道样本数据表示什么。我的问题是,我该如何获取 Channel 和 Frequency 来播放它?这是否有可能?
--(( 变量 ))--
local FileName = "song.wav"
local File = fs.open(FileName, "rb")
local ToHex = "%X"
local Speaker = peripheral.wrap("back")
--(( 函数 ))--
-- 返回十六进制字符串
local function BigEndian(Size)
local Str = ""
for Count = 1,Size do
Str = Str .. string.char(File.read())
end
return Str
end
-- 返回十六进制字符串
local function LittleEndian(Size)
local T = {}
for Count = 1,Size do
table.insert(T,ToHex:format(File.read()))
end
local Str = ""
for Count = #T,1,-1 do
Str = Str .. T[Count]
end
return Str
end
--(( 主程序 ))--
-- 变量
local ChunkID = ""
local ChunkSize = 0
local Format = ""
local Subchunk1ID = ""
local Subchunk1Size = 0
local AudioFormat = 0
local NumChannels = 0
local SampleRate = 0
local ByteRate = 0
local BlockAlign = 0
local BitsPerSample = 0
local Subchunk2ID = ""
local Subchunk2Size = 0
local ExtraPeramSize = 0
-- RIFF 块
ChunkID = BigEndian(4)
ChunkSize = tonumber(LittleEndian(4), 16) + 8
Format = BigEndian(4)
-- 子块 1
Subchunk1ID = BigEndian(4)
Subchunk1Size = tonumber(LittleEndian(4), 16)
AudioFormat = tonumber(LittleEndian(2), 16)
NumChannels = tonumber(LittleEndian(2), 16)
SampleRate = tonumber(LittleEndian(4), 16)
ByteRate = tonumber(LittleEndian(4), 16)
BlockAlign = tonumber(LittleEndian(2), 16)
BitsPerSample = tonumber(LittleEndian(2), 16)
ExtraPeramSize = tonumber(LittleEndian(2), 16)
-- 子块 2
Subchunk2ID = BigEndian(4)
Subchunk2Size = tonumber(LittleEndian(4), 16)
-- 打印输出
print("RIFF 块")
print("- ID: " .. ChunkID)
print("- 大小: " .. ChunkSize)
print("- 格式: " .. Format)
print("子块 1")
print("- ID: " .. Subchunk1ID)
print("- 大小: " .. Subchunk1Size)
print("- 音频格式: " .. AudioFormat)
print("- 通道数: " .. NumChannels)
print("- 采样率: " .. SampleRate)
print("- 每秒字节数: " .. ByteRate)
print("- 数据块对齐单元: " .. BlockAlign)
print("- 每个样本位数: " .. BitsPerSample)
print("子块 2")
print("- ID: " .. Subchunk2ID)
print("- 大小: " .. Subchunk2Size)
local Done = 0
while true do
Done = Done + 1 -- 左通道 右通道 左通道 右通道
--local Sample = {{tonumber(LittleEndian(1),16), tonumber(LittleEndian(1),16)}, {tonumber(LittleEndian(1),16), tonumber(LittleEndian(1),16)}}
local Left = tonumber(LittleEndian(2),16) - 32768
local Right = tonumber(LittleEndian(2),16)
local Average = (Left + Right)/2
Speaker.start(0,Average)
sleep(0)
-- 左通道,右通道
if Done == 5000 then break end
end
Speaker.stop(0)
--(( 结束 ))--
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
WAV 文件存储 PCM 样本数据,它在时间域中。每秒进行多次取样(CD 音频为 44,100 次),以测量该时点上的压力水平,并将其量化以适应给定的比特深度。当你播放这些样本时,它们会近似于原始波形。
图像来自维基百科 PCM 文章
你所要求的是在频率域中取样。这里的样品在更大的间隔(相距约 5-10 毫秒)内取样,并包含组成声音的频谱信息。也就是说,在一段时间内你可以测量到特定频率上的声音量,有可能有 2048 个“盛放”该段时间内特定频率声音的“桶”。这是通过执行原始时间域采样波形的 傅里叶变换(通常在计算机上实现为 FFT)来测量的。
基本上,你现在使用的 API 不能使用你所要求的音频格式 WAV,因为这两种格式有根本性的不同。