编写列表多路分解器
Write a list demultiplexer
我正在尝试处理音频信号的通道。我将信号作为帧列表获取,其中每个帧都有每个通道的样本。现在我想独立处理流然后再次合并它们。所以我要
type Sample = Double
type Frame = [Sample]
type Stream = [Sample]
mux :: [Stream] -> [Frame]
demux :: [Frame] -> [Stream]
process :: Stream -> Stream
output = (mux . (map process) . demux) input
mux [[0.1, -0.1, -0.3], [0.2, 0.4, 0.6]] = [[0.1, 0.2], [-0.1, 0.4], [-0.3, 0.6]]
demux [[0.1, 0.2], [-0.1, 0.4], [-0.3, 0.6]] = [[0.1, -0.1, -0.3], [0.2, 0.4, 0.6]]
因为流很长,mux
和 demux
必须是懒惰的,而不是评估整个列表。
多路复用器看起来很简单。我唯一不喜欢这个版本的是难以阅读的模式匹配。
mux streams@((_:_):_) = map head streams : mux (map tail streams)
mux _ = []
但是我不能轻易想出一个将帧列表转换为流列表的多路分解器。因为在我的例子中不会有超过两个流(立体声音频),我想我可以通过编写两个解复用器来管理,monoDemux
和 stereoDemux
。但我希望一个功能可以在任意数量的频道上工作。我怎样才能懒惰地解复用帧列表?
我认为工作已经为您完成:mux
和 demux
实际上只是 transpose :: [[a]] -> [[a]]
函数:
import Data.List(transpose)
mux = transpose
demux = transpose
这意味着多路复用实际上(至少就列表的列表而言)与多路分解相同。
它生成预期的:
Prelude Data.List> transpose [[0.1, -0.1, -0.3], [0.2, 0.4, 0.6]]
[[0.1,0.2],[-0.1,0.4],[-0.3,0.6]]
Prelude Data.List> transpose [[0.1, 0.2], [-0.1, 0.4], [-0.3, 0.6]]
[[0.1,-0.1,-0.3],[0.2,0.4,0.6]]
transpose
以懒惰的方式工作。我们可以检查 source code:
transpose :: [[a]] -> [[a]]
transpose [] = []
transpose ([] : xss) = transpose xss
transpose ((x:xs) : xss) = (x : [h | (h:_) <- xss]) : transpose (xs : [ t | (_:t) <- xss])
最后一个语句是以下语句的复杂版本:
transpose l = map head l : transpose (map tail l)
我正在尝试处理音频信号的通道。我将信号作为帧列表获取,其中每个帧都有每个通道的样本。现在我想独立处理流然后再次合并它们。所以我要
type Sample = Double
type Frame = [Sample]
type Stream = [Sample]
mux :: [Stream] -> [Frame]
demux :: [Frame] -> [Stream]
process :: Stream -> Stream
output = (mux . (map process) . demux) input
mux [[0.1, -0.1, -0.3], [0.2, 0.4, 0.6]] = [[0.1, 0.2], [-0.1, 0.4], [-0.3, 0.6]]
demux [[0.1, 0.2], [-0.1, 0.4], [-0.3, 0.6]] = [[0.1, -0.1, -0.3], [0.2, 0.4, 0.6]]
因为流很长,mux
和 demux
必须是懒惰的,而不是评估整个列表。
多路复用器看起来很简单。我唯一不喜欢这个版本的是难以阅读的模式匹配。
mux streams@((_:_):_) = map head streams : mux (map tail streams)
mux _ = []
但是我不能轻易想出一个将帧列表转换为流列表的多路分解器。因为在我的例子中不会有超过两个流(立体声音频),我想我可以通过编写两个解复用器来管理,monoDemux
和 stereoDemux
。但我希望一个功能可以在任意数量的频道上工作。我怎样才能懒惰地解复用帧列表?
我认为工作已经为您完成:mux
和 demux
实际上只是 transpose :: [[a]] -> [[a]]
函数:
import Data.List(transpose)
mux = transpose
demux = transpose
这意味着多路复用实际上(至少就列表的列表而言)与多路分解相同。
它生成预期的:
Prelude Data.List> transpose [[0.1, -0.1, -0.3], [0.2, 0.4, 0.6]]
[[0.1,0.2],[-0.1,0.4],[-0.3,0.6]]
Prelude Data.List> transpose [[0.1, 0.2], [-0.1, 0.4], [-0.3, 0.6]]
[[0.1,-0.1,-0.3],[0.2,0.4,0.6]]
transpose
以懒惰的方式工作。我们可以检查 source code:
transpose :: [[a]] -> [[a]] transpose [] = [] transpose ([] : xss) = transpose xss transpose ((x:xs) : xss) = (x : [h | (h:_) <- xss]) : transpose (xs : [ t | (_:t) <- xss])
最后一个语句是以下语句的复杂版本:
transpose l = map head l : transpose (map tail l)