【问题标题】:How do I concat/flatten byte arrays如何连接/展平字节数组
【发布时间】:2013-05-06 12:48:46
【问题描述】:

我正在制作一个生成 .wav 文件的函数。我已经设置了标题,但我遇到了data 本身的问题。我有一个创建 880Hz 正弦波的函数(至少我认为它就是这样做的,但这不是我的问题)——问题是,如何将字节数组的集合转换为仅包含其内容的一个字节数组?这是我最好的尝试:

(defn lil-endian-bytes [i]
  (let [i (int i)]
  (byte-array
    (map #(.byteValue %)
         [(bit-and i 0x000000ff)
          (bit-shift-right (bit-and i 0x0000ff00) 8)
          (bit-shift-right (bit-and i 0x00ff0000) 16)
          (bit-shift-right (bit-and i 0xff000000) 24)]))))

(def leb lil-endian-bytes)

(let [wr (io/output-stream (str name ".wav") :append true)]
  (.write wr
       (byte-array (flatten (concat (map 
         (fn [sample] (leb (* 0xffff (math/sin (+ (* 2 3.14 880) sample)))))
         (range (* duration s-rate)) )))))

但它并没有做我想做的事:将所有字节数组连接到一个向量中,然后连接到一个单字节数组中。对我来说为什么不能这样做是有道理的:它不能连接/展平一个字节[],因为它不是向量;这是一个字节[]。而且它不能将 byte[] 转换为 byte。但是我需要做些什么才能让它发挥作用?

【问题讨论】:

    标签: audio clojure io clojure-java-interop


    【解决方案1】:

    您可能正在寻找类似的东西:

    (byte-array (mapcat seq my-sequence-of-byte-arrays))
    

    【讨论】:

    • 好吧,这实际上与我已经在做的事情并没有什么不同,除非seq 函数中应该发生一些神奇的事情。如果是这样,那是什么魔法?
    • 在您的代码中,您似乎在调用 (concat sequence-of-byte-arrays) 而不是 (concat byte-array-1 byte-array-2 ...)。您可以使用(apply concat (map ...))mapcat 解决此问题。
    【解决方案2】:

    如果您正在处理大型数组,则将要连接的字节数组转换为序列并返回字节数组可能会有点低效。以下是如何连接字节数组,使 java.nio.ByteBuffer 完成繁重的工作:

    (defn concat-byte-arrays [& byte-arrays]
      (when (not-empty byte-arrays)
        (let [total-size (reduce + (map count byte-arrays))
              result     (byte-array total-size)
              bb         (java.nio.ByteBuffer/wrap result)]
          (doseq [ba byte-arrays]
            (.put bb ba))
          result)))
    

    【讨论】:

      【解决方案3】:

      这将很简单:

      您需要组合成单个字节数组的字节数组:

      (def byte-arrays [(byte-array 10 (byte 1))
                        (byte-array 10 (byte 2))
                        (byte-array 10 (byte 3))])
      

      结合:

      (byte-array (for [ar byte-arrays
                        i ar] i))
      

      【讨论】:

      • 这对我来说不像(byte-array (apply concat byte-arrays))(byte-array (mapcat seq byte-arrays)) 那样惯用。为什么要引入所有变量名?正如您所说,您需要组合字节数组,所以只需concat 他们?
      • @ToBeReplaced 我认为问题是您必须以不同于 concat 的方式从byte[] 访问bytes,因为它不是集合,而是byte[]。不过,我肯定是错的。无论哪种方式,这都有效,(byte-array (mapcat list byte-array-collection) 不适合我
      • 你的区分不正确。 Java 数组是可序列化的,这是 concat 工作所需要的。 mapcat list 没有给你想要的输出,因为(list [0 1]) 产生([0 1])。你想要(seq [0 1]),它产生(0 1)
      • 哦,酷。我现在明白了。我没有意识到seq 是一个实际的函数(出于某种原因,我认为您在那里使用了对某种函数类型的某种引用)。应该更努力地考虑一下。我还是个初学者。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-13
      • 2020-01-03
      • 1970-01-01
      • 2017-07-09
      • 2018-03-05
      • 2012-03-21
      相关资源
      最近更新 更多