写一个列表解复用器

sba*_*sba 1 haskell multiplexing data-structures

我正在尝试处理音频信号的通道.我得到信号作为帧的列表,其中每个帧具有每个通道的样本.现在我想独立处理流然后再合并它们.所以我想要

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]]
Run Code Online (Sandbox Code Playgroud)

因为流很长,mux而且demux必须是懒惰的而不是评估整个列表.

多路复用器似乎很简单.我唯一不喜欢这个版本的是难以阅读的模式匹配.

mux streams@((_:_):_) = map head streams : mux (map tail streams)
mux _ = []
Run Code Online (Sandbox Code Playgroud)

但是,我不能轻易想出一个将帧列表转换为流列表的解复用器.因为在我的情况下,也不会有两个以上的数据流(立体声),我想我可以写两个分流器管理monoDemuxstereoDemux.但我希望一个功能可以在任意数量的通道上工作.我怎么能懒得拆分框架列表呢?

Wil*_*sem 5

我认为,这项工作已经为你做了:既muxdemux,实际上只是transpose :: [[a]] -> [[a]]功能:

import Data.List(transpose)

mux = transpose
demux = transpose
Run Code Online (Sandbox Code Playgroud)

因此,这意味着多路复用实际上(至少就列表列表而言)与多路分解相同.

它产生了预期的:

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]]
Run Code Online (Sandbox Code Playgroud)

transpose以懒惰的方式工作.我们可以查看源代码:

transpose               :: [[a]] -> [[a]]
transpose []             = []
transpose ([]   : xss)   = transpose xss
transpose ((x:xs) : xss) = (x : [h | (h:_) <- xss]) : transpose (xs : [ t | (_:t) <- xss])
Run Code Online (Sandbox Code Playgroud)

最后一个语句是一个复杂的版本:

transpose l = map head l : transpose (map tail l)
Run Code Online (Sandbox Code Playgroud)

  • 这个定义是否意味着`transpose`是一个部分函数?我的意思是,如果我说'transpose [[1],[]]`,它会破坏,对吗? (2认同)