【问题标题】:Ocaml : how to transform note to musical chordsOcaml:如何将音符转换为和弦
【发布时间】:2014-10-12 13:34:44
【问题描述】:

我想从 ocaml 中的音符和列表创建和弦。

结构:

type objet_musical =
    | Note of (int * int * int)
    | Silence of int
    | Sequence of objet_musical list
    | Parallel of objet_musical list

还有名单

let transposition = [(0,4,7);(0,3,7);(0,4,8);(0,3,6)];;

非常感谢您的回答。 玛丽

【问题讨论】:

    标签: ocaml music-notation


    【解决方案1】:

    大问题应该分小步解决。首先让我们创建一个函数transpose_objet,它将接受一个带有单个转置的单个对象,即一个移位,并返回一个新对象,该对象以指定移位的音高进行转置。

    (** [transpose_objet obj shift] takes a musical object [obj] and
        transposes it pitch to a value [shift] *)
    let rec transpose_objet obj shift : objet_musical = match obj with
      | Note (h,v,d) -> Note (h + shift, v, d)
      | Silence t -> Silence t
      | Sequence objs ->
        Sequence (List.map (fun obj -> transpose_objet obj shift) objs)
      | Parallel objs ->
        Parallel (List.map (fun obj -> transpose_objet obj shift) objs)
    

    接下来,让我们尝试创建一个由三个换位组成的和弦。所以我们把一个三连音和一个对象并行播放(我认为这就是和弦的意思)。我们将这个函数命名为chord_of_transposition

    (** [chord_of_transposition obj tlist] takes a musical [obj] and a triplet,
        where every element of triplet is a number to which the pitch
        should be transposed, and creates a chord *)
    let chord_of_transposition obj (t1,t2,t3) : objet_musical =
          Parallel [transpose_objet obj t1;
                    transpose_objet obj t2;
                    transpose_objet obj t3]
    

    通过这个方便的函数,我们可以处理一个组合三元组列表。让我们编写一个函数chords_of_transpositions 所以我们想获取一个音乐对象和转置列表,并从每个转置创建一个和弦。我们希望它仍然是一个音乐对象,所以我们使用构造函数 Sequence 从结果列表创建一个对象。

    (** [chords_of_transpositions obj transpositions] takes a list of
        triplets, where each element of triplet is value by which a
        musical object should be shifted and creates a sequence of musical
        objects that will play a chords from each transposition.  *)
    let chords_of_transpositions obj ts : objet_musical =
      Sequence (List.map (chord_of_transposition obj) ts)
    

    作为一个练习,我建议你重写函数chord_of_composition,而不会出现难看的重复(提示,使用List.map)。

    作为第二个练习,尝试从transpose_objet 函数中删除代码重复。您是否注意到 ParallelSequence 子句的模式是相同的。

    作为第三个练习,尝试重写您的代码,以便您的转置列表不是由三元组组成,而是由 n-plets 组成,如下所示:

    let transposition = [[0;4;7];[0;3;7]; [0;8]; []; [0;3;6]]
    

    空列表代表静音。

    回答一个新问题

    问题

    我试试这个

    let seq1= Sequence((Note(60,100,1000)):: (Note (64,100,500)):: (Note (62,100,500)):: (Silence(1000)):: (Note (67,100,1000)):: []) 
    

    let transposition= [(0,4,7);(0,3,7);(0,4,8);(0,3,6)];; 
    

    和你的提议

    let chordify om tp : objet_musical= Sequence (List.map (chordify om)tp);; 
    

    和测试

    让 test= chordify seq1 转置;;

    但是top Ocaml返回

    Error: This expression has type (int * int * int) list but an expression was expected   of type int list list Type int * int * int is not compatible with type int list . 
    

    如何解决?

    回答

    首先,我想指出,我们开始大力推动 SO。这是一个问答网站,而不是论坛。我已经为你做了一些工作,但我看不出你正在尽自己的一份力。我来这里不是为了做你的功课,而是帮助你解决关于 OCaml 和编程的一般问题。我的建议是从一本关于 OCaml 的好教科书开始,然后先学习它。只是尝试随机复制粘贴代码,直到编译不是一个好主意。现在,回到你的问题。

    首先,您可以使用更简洁的符号:[1;2;3],而不是像1 :: 2 :: 3 :: [] 这样粗略地构建列表。这样您的序列就可以通过以下方式重写:

    let seq1 = Sequence [
        Note (60,100,1000);
        Note (64,100,500);
        Note (62,100,500);
        Silence (1000);
        Note (67,100,1000)
    ]
    

    接下来,你的函数

    let chordify om tp : objet_musical =
      Sequence (List.map (chordify om) tp)
    

    指的是一些未绑定的符号chordify。如果你想在它自己的体内调用一个函数,你需要让它递归,即将rec添加到let表达式:

    let rec chordify om tp : objet_musical =
      Sequence (List.map (chordify om) tp)
    

    我认为,您已经将该函数两次推送到 OCaml 顶层,因此您有效地进行了以下定义。

    let chordify om tp : objet_musical =
      Sequence (List.map (chordify om) tp)
    
    let chordify om tp : objet_musical =
      Sequence (List.map (chordify om) tp)
    

    但是,相反,您真正想要做的是不调用函数cordify,而是调用函数chord_of_transposition,这将转换一个objet_musical,使其具有特定的转置实例,如下所示:

    let chordify om tp : objet_musical =
      Sequence (List.map (chord_of_transposition om) tp)
    

    所以我们得出的定义等于我之前提供的函数chords_of_transpositions 的定义。

    【讨论】:

    • 我必须将 objet_musical 与换位列表关联起来。
    • 我必须将 objet_musical 与换位列表相关联。例如,如果 note do=60 并且 note*list => 和弦 (60,64,67)。
    • 好的,现在我有两个问题:(1) Note 构造函数中的三元组 (int * int * int) 是什么?它是否以某种方式与音高、八度、持续时间或音量相对应? (2) 换位表中的三元组是什么意思?您是否需要将每个object_musical 转置为三个不同的转置?
    • 三元组表示(高度、体积、持续时间)。是的,我想在列表转置中转置每个 object_musical。
    • 高度是间距?我不明白第二部分:你有一个objet_musical 的列表,你有一个换位三连音的列表,其中每个三连音代表一个单独的音高换位?你想以某种方式将一个应用到另一个上,这样每个objet_musical 都会被复制三倍?
    猜你喜欢
    • 2012-07-19
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    • 2016-10-05
    • 2012-05-12
    • 2013-12-24
    • 2021-08-13
    相关资源
    最近更新 更多