國立臺灣師範大學 - ntnurportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019....

112
國立臺灣師範大學 音樂學系碩士班作曲組學位論文 電腦音樂創作媒介:Eclipse Java 程式語言概念、應用與實作探討 New Way for Computer Music Composing EclipseThe concept of Java program language 指導教授:李和莆 博士 研究生:鄭蒼嶽 2012 11

Upload: others

Post on 27-Feb-2021

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

國立臺灣師範大學

音樂學系碩士班作曲組學位論文

電腦音樂創作媒介:Eclipse

Java 程式語言概念、應用與實作探討

New Way for Computer Music Composing “Eclipse”

The concept of Java program language

指導教授:李和莆 博士

研究生:鄭蒼嶽 撰

2012 年 11 月

Page 2: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

i

前言

對於筆者而言,接觸到電腦音樂的契機是在研究所期間,經由海外進修的學

長在一次回國講座中介紹到這項新興的創作手法,同時也因此得知這項技術在國

內尚未有前人做過研究以及將其應用到音樂創作一途。因此經過長期思考後,在

訂立論文主題時,考慮到其創新及學術上的價值,並且承蒙恩師李文彬教授的支

持與同意,最終選擇了此一跨領域主題為研究的核心。

最初從事此項研究時,困難之處莫過於要從頭學習跨領域技術層面的知識,

像是程式語言的編寫、排列、串聯等等,到最後把自身所學的音樂創作技術加以

合併應用到作品中。而這類型的電腦音樂作品也是筆者過去未曾接觸和嘗試的,

就整體而言,不管是學習編程還是創作的部分都十分具有挑戰性。

為此,在此要感謝人在海外的邱明慶學長及資工相關專業的王尚平同學等人

在論文期間提供諮詢和解答。而最終作品在發表的呈現上,也非常感謝演奏者蘇

品嘉同學能一同合作將其完成,當然也要感謝在研究所期間指導教授李文彬教授

以及論文口試委員陳茂萱教授及陳瓊瑜副教授在論文口試時提供的建議;另外也

感謝所有在論文研究這段時間內支持、幫助過筆者的親人、朋友、師長及學長姐

們。

最後,由於資訊工程並非筆者之過去所學之專科本業,因此在不同領域的狀

況下,儘管在寫作過程盡力追求嚴謹,恐難以力求完美,惟筆者才疏學淺,如有

遺漏、錯誤之處,望各位先進師長不吝指教,並且亦期望本論文能夠為日後期望

以 Java 程式語言為創作方式的後進提供明確易懂的說明及範例。

Page 3: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

ii

中文摘要

電腦投入音樂創作領域中至今已過五十餘年,在科技日益進步的今日,越來

越多對於音樂創作、音樂展演、音樂教育上有所幫助的程式、設備等也不停的改

良並且研發出來,因此,也使得電腦音樂在現今全世界的音樂領域中已成為不同

於以往學術創作的另一股潮流。在國內,電腦音樂也逐漸受到音樂創作者們的注

意,使得越來越多人投入這個領域,雖然尚未受到廣泛運用,但這項技術的引入,

對於學術音樂創作上的影響,不僅提供了新的創作元素,同時更增添許多新的可

能性,擴展國人學術創作的深度及廣度。

目前國內的電腦音樂在程式的使用上是以 Max/Msp 為主流,然而,本論文將

要探究是以在資訊工程領域中已受到廣泛運用的 Java 程式語言為創作基礎的一種

新的電腦音樂創作平台-Eclipse。內容將從程式語言元素及敘述式的介紹、基礎

的編程範例、音樂分析以及提供實際創作作品為應用實例,進而推展出跨領域合

作和技術統合對於音樂創作發展上的可能性,也期望最終能以此方式使得音樂能

在資訊發達的現代,能更加容易推廣至大眾的生活當中。

關鍵字:Eclipse、Java 程式語言、jMusic。

Page 4: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

iii

Abstract

Computer has been involved in music composition since 1950s. Nowadays, with

the advance of science and technology, more and more programs and equipment are

invented and improved to assist in musical composition, music performance and music

education. Known as “computer music”, musical composition using computer, a way

completely different from traditional academic composition, has therefore become a

popular trend these days. In Taiwan, composers gradually noticed the emergence of

computerized music, which makes more and more people devoted to the field. Although

currently the technique has not been applied widely, this introduction not only provides

new element to music but also adds new possibility. In the meantime, having strong

influence on the quality of music, this fresh technique expands the depth and width of

academic composition and broadens people’s horizons.

Now the Max/Msp is the most popular program in Taiwan. However, the research

in this thesis is about how to use another well-known interface in the field of computer

science named “Eclipse” on the music composing. From introducing and programming

the basic operators, methods, statements to music analyzing and music composing, this

thesis is suitable for those beginners who want to use Java language to compose music.

Provided with the application of examples and experimental composition, I hope it will

push the cross-field cooperation. Furthermore, it can be easier to apply this technique to

spread classical music and modern compositions to the general public.

Keywords: Eclipse, Java Program language, jMusic.

Page 5: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

iv

目次

前言 ................................................................................................................................ i

中文摘要 ....................................................................................................................... ii

英文摘要 ...................................................................................................................... iii

目次 .............................................................................................................................. iv

第一章 緒論 ............................................................................................................... 1

第一節 研究目的 ........................................................................................... 4

第二節 研究範圍 ........................................................................................... 5

第三節 研究方法 ........................................................................................... 6

第二章 電腦音樂 ....................................................................................................... 7

第一節 Max/Msp ............................................................................................ 8

第二節 Eclipse/jMusic ................................................................................. 10

第三節 Max 與 Eclipse 比較 ....................................................................... 13

第三章 Eclipse 內涵 ................................................................................................. 15

第一節 Java 程式語言簡介與基本應用 ..................................................... 15

(一)Java 程式語言的內涵與背景

(二) Java 程式開發環境

(三) Java 程式編寫基本架構與列印字元

第二節 Java 語言下的數學與邏輯 ............................................................. 26

(一)Java 中的數學概念

(二)Java 語言中的選擇敘述式

(三)Java 語言中的迴圈敘述式

(四)Java 語言中的陣列

(五)Java 語言中的數學類別和亂數類別

第三節 數學概念帶入音樂 ......................................................................... 48

(一)jMusic 中 MIDI 製作相關基礎常用物件名稱

(二)近代音樂之於 Java 程式語言

第四章 作品分析,作品《幻實之鏡》 ................................................................. 67

第一節 創作概念 ......................................................................................... 67

第二節 創作歷程 ......................................................................................... 69

第三節 作品分析 ......................................................................................... 71

Page 6: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

v

第五章 結論 ............................................................................................................. 85

參考文獻

附錄

Page 7: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

1

第一章 緒論

音樂創作的發展,自十九世紀末進入二十世紀這個從原先調性音樂(Tonal

Music)轉型到非調性音樂(Atonal Music)的過渡期開始,作曲家們為了突破以往的

窠臼,在創作上開始各式各樣的大膽嘗試,從最開始仍以傳統樂器演奏為基礎,

打破調性結構的十二音列 (Twelve-tone),到以音列的手法為基礎的序列音樂

(Serialism)。後來更是為了追求音響上的突破,使得電子、科技等元素也成為音樂

創作中的一部份。

說到科技對於在音樂創作上的影響,最早的起源可以追朔回二十世紀初,電

子音樂(Electroacoustic Music)的發跡。一開始,如同上段所言,只因為原有的各種

古典樂器所發出的音色對於作曲家們而言已經不再滿足;因此,作曲家們開始朝

向科技方面尋求新的出路,發明出各種符合自己需要的、藉著電子合成出獨有音

色的各式電子樂器,有些是將舊有的古典樂器電子化、其餘有些是完全創新、有

著機械外表的樂器。

在當時作曲家的作品中用到電子樂器的例子,像是法國作曲家瓦瑞斯(Edgard

Varese, 1886-1965)於 1934 年創作的作品《赤道》(Ecuatorial, 1934)中就使用了兩台

「特雷蒙」 (Theremin), 1 另外同為法國作曲家的梅湘 (Oliver Messiaen,

1908-1992),在他 1937 年中;的作品《美泉節慶》(Fê te des belles eaux, 1937)中也

1 特雷蒙琴(Teremin):由特爾門(Lev Termen, 1896-1993)於 1920 年發明的電子樂器,

藉由操作震盪器(oscillator)的方式改變頻率來演奏。

Page 8: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

2

用到六台「馬特農」(Martenot),2 其他電子樂器還有漢蒙德(Laurens Hammond,

1895-1973)於 1933 至 34 年間發明的「電子管風琴」(Electronic organ)。同時,作

曲家米堯(Darius Milhuad, 1892-1974)、亨德密特(Paul Hindmith, 1895-1963)、瓦瑞

斯等人也藉由當時的留聲機(phonographs)技術去改變早期創作錄音的速率,造成音

高的改變,而真正第一首以留聲機技術來創作的作曲家是約翰・凱基的(John Cage,

1912-1992)於 1939 年的作品《第一號幻想風景》(Imaginary Landscape No.1, 1939)。

接續著是利用錄音技術而得以發展的具象音樂(Musique Concrete),最早是由

法國人薛費爾(Pierre Schaeffer, 1910- )藉由種種不同的方式加工錄下各式各樣現實

中「自然的」聲音,像是改變錄音速率、將錄音本身逆行(tape reversal)以及混合不

同的聲音(overdubbing)等等。而這些技術真正實際應用、並創作成完整的作品,則

是在法國作曲家亨利(Pierre Henry, 1927- )1950 年的作品《一個人的交響曲》

(Symphony for a Man Alone, 1950),在這首作品中可以聽到,作曲家現實中錄下的

呼吸聲、笑聲、講話聲這些人聲,混合了交響樂、腳步聲等其他聲音。

繼電子樂器跟錄音技術之後,真正完全的電子音樂的發跡,則從德國作曲家

艾麥特(Herbert Eimert, 1897- )在科隆設立的電子工作室開始。艾麥特以錄音後制的

技術為基礎,同時也加入新的設備 -震盪器 (Oscillator)和聲音產生裝置 (Noise

generator),藉由這兩種新的裝置,作曲家不需再仰賴預錄的現實中聲音為創作基

礎,可以直接產生他們想要的各式電子聲音。如此的技術發展對於序列音樂

(Serialism)的作曲家們而言是一大福音,這代表著他們能藉此他們不止能操控音高

和長短,也能操控聲音的元素本身。而首位在作品中體現這項技術的作曲家,即

為史托克豪森(Karlheinz Stockhausen, 1928-2007)分別於 1953 和 1954 創作的《一號

2 馬特農琴(Martenot):由馬特農(Maurice Martenot, 1898-1980)於 1928 年發明的電子

樂器,同樣也能持續的在一定的音域內演奏,但在音高的控制上做了改良,同時也具有更

多樣性的音色變化。

Page 9: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

3

研究》(Study I, 1953)以及《二號研究》(Study II, 1954)兩首作品,而在 1960 年代之

後,電子音樂已經不像早期僅為嘗試性、實驗性的創作,反而成為當十音樂創作

不可或缺的一個要素,如此的景像大約持續到了 1970 年代左右。

電子音樂崛起後,電腦音樂也隨之在 1950 年代後期出現。最初能在電腦上使

用的聲音合成程式出現於 1957 年,由美國電子工程師馬修斯(Max V. Matthews,

1926-2011)在貝爾實驗室中研發完成的第一套能產生音樂聲響程式。而這套程式在

1964 年首先在普林斯頓大學中使用,史丹佛大學也隨後跟進使用;歐洲方面,最

早的電腦音樂工作室亦在 1964 年設立在荷蘭的烏德勒支(Utrecht),但早年的電腦

音樂,儘管是一項嶄新的技術,卻沒有引起大量作曲家們的興趣,反而是到了 1980

年代之後才逐漸擴展至今。

Page 10: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

4

第一節 研究目的

電腦科技的發展對現在當代的台灣作曲家們而言,是一個既具有發展潛力卻

又不敢輕易嘗試的領域,它時時刻刻都不斷進步、替作曲家們提供新的意外跟驚

喜,也使得眾多作曲家都亟欲去嘗試。但進步也意味著它本身將存在各式各樣的

變因,也成為這塊領域之所以讓人卻步的原因之一,另一個原因是,它除了需要

作曲家們在音樂創作領域中所學習、具備的理論和技術外;更甚者,在於電腦操

作的技術,不同於紙筆創作寫在五線譜上的每個記號、音符等等,需要的是跨領

域的、對於完全截然不同的各式指令上的專業知識,這些也成為對於大部分作曲

家最大的挑戰。

在台灣,隨著時間的流逝,音樂創作和展演的領域,從早期年長、資深的前

輩作曲家們的紙筆創作,到現在,隨著環境改變,改變了作曲家們對於聲響上的

要求,也因此為了追求新的概念跟聲響的需要,加上部分受制於演出人事、經費、

聽眾等考量,越來越多中生代作曲家及新生代的學生投入電腦音樂的創作和應用。

而國內現在音樂創作的慣用程式,目前台灣是以 Max 為主流。然而,筆者在

本論文中,想要探討的是卻是以 Java 程式語言創作音樂的另一個程式:Eclipse,

希望以此提供在電腦音樂創作上的另一個途徑。

Page 11: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

5

第二節 研究範圍

本論文研究範圍,由於預設是以非資訊工程背景的使用者為出發點而撰寫;

因此將從 Eclipse 的背景沿革、Java 程式語言的發展背景為開端做基本介紹。

接著是針對 Eclipse 程式創作時利用的 jMusic 所需的 Java 程式語言為基礎,

從各種基本的運算子、基本邏輯的運算式…如此由淺入深的介紹並配合操作範例

說明。

在基本的敘述式介紹完成後,進一步的,把這些程式設計上的邏輯概念應用

到套用了 jMusic 下的音樂創作層面。在這個部分,筆者將選擇由創作出經典作品

《四分三十三秒》(4’ 33″, 1952)的作曲家約翰・凱基(John Cage, 1912-1992)所提倡

在 1950 年代發跡的不確定主義(Indeterminacy) 說明如何以程式語言做出隨機的概

念,1960 年代盛行一時的極簡主義(Minimalism)則以選擇出特定作品並分析的方式

以最後以融合數學概念的「正弦波」(Sinewave)、「音雲」(Sound Cloud)為基礎的

範例分析;希望儘管在有限狀況或範例的分析之下,可以提供明確如何將數學、

邏輯和音樂創作三者結合的概念。

最後,將這些概念應用到實際作品創作,以階段性引導為探討目標,著重於

相關作品分析與應用手法探討,並且提供實際應用之例證,希望使得其他讀者能

以此為使用此程式的入門操作之參考。

Page 12: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

6

第三節 研究方法

本論文之研究方法分為以下幾種步驟:

一、相關文獻資料探討:提供電腦音樂兩大系統程式之發展背景-Max/Msp 和

jMusic,並比較其不同之處。

二、Java 程式語言基礎概念的介紹:從各式基礎元素的介紹為開端,到完整

的指令、複合指令的分析

三、Java 程式語言之於音樂領域應用:以近代音樂各式風格、主義的作品為

例探討並分析。

四、實際作品操作及應用:透過在作品中實際融入,以此使得各階段性組合

的概念能更加清晰。

五、綜合歸結:以上述各種方法研討,歸結提出 Eclipse 程式應用之我見,作

為本論文研究結論。

在本論文中,所有範例編號將以全形中文數字來編號,且以不分章節的型式

編列,也就是說編號將會從一開始持續往下列出,不隨著章節更新重新編排,如

「範例一」、「範例十五」。

而表格編號將以「表 x-x-x」的方式來編列,第一碼“x”為章數,第二碼“x”為

節數,最後一碼“x”則為同一節中第幾個表格,舉例來說,在第三章第二節中第五

個表格將會編列成「表 3-2-5」以方便閱讀;圖片與譜例也將會以相同方式給予編

號,但圖片第三碼將會以小寫英文字母編寫,如「圖 3-1-a」,譜例部分第三碼將以

羅馬數字編寫,如「譜例 3-1-i」。

Page 13: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

7

第二章 電腦音樂

電腦音樂的創作,在現今各式軟體出現前,也經歷過很長時間的演進。最初,

一些作曲家將電腦做為後製、加工錄音的工具,一部分則是將電腦為操作電子音

樂的媒介;直到 50 年代,終於有作曲家提出純粹以電腦來創作的概念,1956 年,

由希勒(Lejaren Hiller, 1924-1994)和艾薩克遜(Leonard Isaacson, 1909-1997)聯合創

作出弦樂四重奏《依里亞克組曲》(Illiac Suite, 1956),即是在不同樂章以不同電腦

程式模仿過去作曲家的寫作風格來寫作;後來 60 年代早期,希臘裔法籍作曲家瑟

納基斯(Iannis Xenakis, 1922-2001)也利用了電腦演算技術去創作音樂,像是他在

1962 年完成的弦樂四重奏作品《四分之 ST》(ST/4, 1962)即為一個例子。

但對於電腦現代音樂創作發展上具有顯著影響力的轉捩點,是於 1976 年在巴

黎,由法國作曲家布列茲(Pierre Boulez, 1925-)發起,在法國政府支持下成立的法

國 音 樂 與 聲 學 協 調 研 究 學 院 (Institut de Recherche et de Coordination

Acoustique/Musique, 簡稱 IRCAM,後文亦以此稱之)的出現;IRCAM 中匯集各方

科學家和音樂家,致力於研究在科學上的音樂現象;同時,IRCAM 也配有最先進

的電腦設備,除了作為將各式研究與音樂結合之用外,也以這些設備做為聲音合

成以及即使演算的樂器平台;除了許多知名的作曲家都曾經在 IRCAM 中工作過

外,現在年輕一輩的作曲家們,也都深受其影響。3

3 本段文字彙整自 Morgan, Robert P.. Twentieth-Century Music: A History of

Musical Style in Modern Europe and America. New York: Norton, 1991.

Page 14: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

8

第一節 Max/Msp

Max 程式,最初是在 1980 年中期,由位在法國 IRCAM 工作室的帕凱特(Miller

Puckette, 1959-, 後文簡稱為帕凱特)為了麥金塔電腦(Macintosh, 簡稱 Mac)而設

計。大量實際應用上,則於 1989 年,當時 IRCAM 使用 NeXT 軟體公司生產出的

新的「即時演算合成器效能卡」(Real-Time Synthesizer Card)又稱 IRCAM Signal

Processing Workstaion(簡稱 ISPW),帕凱特針對這個效能卡引入這套新的程式,也

就是被稱為 Max/FTS 的這套程式。

1990年,Max程式藉由Opcode Systems公司開始了對外商業性的販售。自 1999

年至今,則轉為 Cycling’74 公司出版、支持並加以販售。在 1996 年,帕凱特開始

研發新的程式-Pure Data(簡稱為 PD)。4

在 PD 研發完成後不久,吉卡瑞里(David Zicarelli,後文簡稱為吉卡瑞里)開始

研發具有 PD 基礎演算技術,同時在功能上也 Max/FTS 的啟發,最終行成了

Max/MSP(但當時還沒應用到 PD 中),也以此為基礎不斷改進,成為今日以 PD 為

基礎來創作的 Max/MSP,最後附上 Max 程式開發的歷史簡表(見表 2-1-1):

4 Pure Data(PD):研發目標上和 Max/FTS 不同,但卻同樣具有即時信號演算能力

(Real-Time Signal Processing)。儘管最初是在 SGI 平台上開發,現在 PD 可以在 Windows、

Linux 和 Mac 系統中運行。

Page 15: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

9

【表 2-1-1】Max 開發歷史簡表(以官方查詢到的版本年代為準):

年(西元) 事件

1989 帕凱特研發出 Max/FTS。

1990 Opcode Systems 開始對外販售 Max/FTS。

1996 帕凱特開始從事研發 PD,吉卡瑞里隨之研發 Max/MSP。

1999 Cycling’ 74 公司取得出版權。

2002 Max/MSP 4.1 發布。

2003 Max/MSP 4.2.1 發布。

2004 Max/MSP 4.3.2 發布。

2006 Max/MSP 4.5.7 發布。

2007 Max/MSP 4.6 發布。

2011 Max/MSP 5 發布。

2012 Max/MSP 6 發布。

Page 16: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

10

第二節 Eclipse/jMusic

一、 Eclipse 發展背景:

Eclipse這個程式是在 1999年由 OTI(Object Technology International)和 IBM公

司共同合作開發而成的,主要是設計成一個整合開發環境(Integrated Development

Enviroment, 後文簡稱為 IDE)。5

其前身據說為 Visual Age,但由於 Visual Age 無法由第三方進行擴充,所以開

發團隊才進而彙整當時其他 IDE 的共通項目開發 Eclipse,開發完成發布後,Eclipse

由於其效能及提供免費下載使用,很快就廣為受到利用。其開發歷史年表如本節

附表(見表 2-2-1)。

Eclipse 是開放原始碼的綜合開發環境,它是以 EPL(Eclipse Public Lisence)這

一原始碼授權發布。也因此使得它得以讓人免費使用,也能自由閱覽它的原始碼。

而它受到廣大利用的原因,除了它免費容易取得之外,它在功能上的高完成度、

跨平台以及外掛程式的擴充性,也是讓眾多使用者選擇這個程式的原因。

就完成度而言,它備有建立、編寫、執行、除錯 Java 程式碼之基礎功能,同

時也具備了協作版本系統(Concurrent Versions System, 簡稱 CVS)6 之類的團隊功

能等等。就跨平台開發而言,它雖然是以 Java 語言為開發的基礎,但藉由加入外

掛程式的方式,它亦可以 C、C#、HTML、XML 等語言進行開發。就外掛程式的

擴充性而言,除了上述項目中提到,可以使其以不同程式語言進行開發外,Eclipse

5 整合開發環境(IDE):是一種輔助程式開發人員開發軟體的應用軟體,其中通常包

括了程式語言編輯器、自動建立工具、除錯器等等,有些 IDE 可以支援多種程式語言,

但大多還是針對特定的程式語言來研發。 6 協作版本系統(CVS):又稱併發版本系統,是一種版本控制系統,方便軟體的開發

商和使用者協同工作,也因此,能達到多方共同更改和改進,同時也能夠確保由不同人所

編輯的同一程式都能保持同步。

Page 17: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

11

開發廠商和其他第三方廠商亦提供俱各種不同功能的需附費、免費的外掛程式,

提供使用者取其所需、客製自己的 Eclipse;而本論文中在創作上使用的 jMusic 也

算是這種外掛程式的一種。

【表 2-2-1】Eclipse 開發版本歷史年表

年(西元) 事件

1999 OTI 和 IBM 開始開發 Eclipse。

2000 Eclipse Tech 發布。

2001 6 月 Eclipse 0.9 發布,10 月 Eclipse 1.0 版本發布。

11 月 IBM 公司開放原始碼。

2002 Eclipse 2.0 發布。

2003 Eclipse 2.1 發布。

2004 Eclipse 3.0 發布。

2005 Eclipse 3.1 發布。

2006 Eclipse 3.2 (Callisto) 發布。

2007 Eclipse 3.3 (Europa) 發布。

2008 Eclipse 3.4 (Ganymede) 發布。

2009 Eclipse 3.5 (Galileo) 發布。

2010 Eclipse 3.6 (Helios) 發布。

2011 Eclipse 3.7 (Ilndigo) 發布。

2012 Eclipse 4.2 (Juno) 發布。

Page 18: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

12

二、 jMusic 發展背景:

對於 jMusic 的研究,始於 1990 年晚期,由澳洲昆士蘭科技大學(Queensland

University of Technology, 簡稱 QUT)的音樂學院研發。

研發的初衷是希望能將 jMusic 作為在電腦音樂創作的一個協助平台。在設計

上,jMusic 被設計為一個開方式的空間,但其中內涵了經過組織過、結構化的一

些函式指令;因此,在操作上不需因需求而去編寫個別單一類別,只需要查詢既

有類別指令即可,對於提升操作上的便利性有很大的幫助;而除了音樂創作外,

jMusic 亦可作為分析以及音樂教育之用途。

jMusic 同時具有一個類別庫(Liberaries)。以類別庫而言,jMusic 在操作上是以

java 的程式語言在操作,同時,藉由 java 所完成的檔案也較易於在跨系統的各式

平台上使用,換言之,此類型的檔案在其中若沒有任何指令是特別呼叫某單一系

統中的程式時,它能在微軟公司所生產的 windows系統和麥金塔公司所生產的mac

系統中運作。

最後,藉由 jMusic 創作出的作品,能以存取為樂器數位類型的檔案(Music

Instrument Digital Interface, 簡稱為 MIDI)的方式,匯出和匯入其他不同類型的音樂

創作軟體,像是最常見的 Finale 和 Sibelius 等等;藉由這種方式,能將這些程式語

言樂譜化,提升其使用上的便利性。

Page 19: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

13

第三節 Max 與 Eclipse 比較

關於 Max 和 Eclipse 兩個程式間的差異,從程式本質來比較,Max 是一種附合

型態的程式(Max 處理的是訊息、MSP 處理音樂訊號以及 Jitter 作為影像處理),在

操作上,Max 已是經程式設計師設計好的一個完整程式,使用者能在事先經過規

劃並設計過的介面下進行指令的連結或是額外載入或串連其他程式。這樣也代表

著使用者們是在所需功能都已備齊的情況中工作,可以自由載入音訊檔案做後置

調整或是自由混合成自己要的電子樂器等工作,其成品的性質屬於一種資料,舉

個例子,就像是以打譜軟體 Finale 所完成的檔案,在沒有轉換成圖檔的情況下,

就無法在沒有安裝該程式的電腦中使用檔案,即便是執行可以讀取的圖檔,缺少

了程式主體也無法進行編輯的工作;倘若是在沒有安裝 Max 這套軟體的電腦中,

也是無法進行編輯的功能。

反觀 Eclipse,雖然同樣為一種創作平台,但 Eclipse 創作時所操作的是屬於基

本的程式碼編寫,所謂的程式碼,它的運作,凡舉電腦開機後如何持續運行,或

是當使用者在使用任何一個程式中一個選單的條列、在選完選項後要執行什麼功

能等等,都是經由程式設計師將這些程式碼事先建構完才有辦法達成;另外成品

導向方向,Eclipse 創作出的成本不論其內容的複雜度,都已經是屬於一種程式,

這也意味著,若是在編寫程式時把條件本身設定好,它完成後將能在各種平台上

被執行,包括現在極為風行的各種平板電腦及手機。

就程式介面而言,Eclipse 在有經驗的程式設計者使用下,可以憑藉自己喜好

跟習慣自由調整,程式本身只是一個根基,而 Max 則是已經預先設定好定型的操

作介面(像是物件、訊息等指令的不同);操作用語上,Eclipse 使用的 Java 語言是

Page 20: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

14

承襲並整合過去慣用的程式語言而成,因此對於非音樂專業背景的使用者而言,

所需要的只是多出來對於音樂創作上一些指令的理解,剩餘的可以憑藉自己編寫

程式的邏輯進行創作;而 Max 有著獨特的操作方式與連結上的邏輯概念,操作上

屬於全新的獨立技術,對於不管是否為音樂專業背景出生的操作者,都需要從零

開始學習,無法快速的上手。

Page 21: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

15

第三章 Eclipse 內涵

第一節 Java 程式語言簡介與基本應用

一、 Java 程式語言的內涵與背景

Java程式語言的開發始於 1991年昇陽公司(Sun Microsystems)於公司內部設立

了一個以 C++語言7 為基礎發展新的程式語言的專案,此專案在當時雖然一度面臨

取消的危機,但隨著 1993 年全球資訊網路(World Wide Web)的興起,昇陽公司評

估 Java程式語言對於建立帶有互動介面和動畫的動態內容(dynamic content)類型網

頁上具有潛力,因此使得研究專案得以繼續,並在 1995 年的 5 月對外發布有關 Java

的消息。

而現在的 Java 則是由 Oracle 公司代理,按照用途分成標準版(Java Standard

Edition, 簡稱為 Java SE)、企業版(Java Enterprise Edition, 簡稱為 Java EE, 用於大

型、分散式的網路應用)、精簡版(Java Micro Edition, 簡稱為 Java ME, 用於小型且

記憶體受限的裝置)。

Java 程式是由類別(class)所組成,類別之中包涵方法(method),它能夠執行工

7 C 與 C++語言:C語言是由利奇(Dennis Ritchie, 1941-2011)於 1972 年以 1967 年理

查(Martin Richards, 1940- )所研發的 BCPL 和 1972 年由湯普森(Ken Thompson, 1943-)所研

發的 B 兩種語言為基礎研發而成,而 C++語言由史特勞斯特魯普(Bjarne Stroustrup, 1950- )

以 C 語言為基礎加入「物件導向程式設計」的功能擴充,使得它同時能個別和混合使用 C

和物件導向兩種方式撰寫程式。

Page 22: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

16

作,並且也能在完成工作後回傳資訊。程式設計師可以依其所需建置自己所需的

各個類別,但也可以利用已經經過彙整的 Java 類別庫(Java class libraries, 後文以

API 簡稱之)來撰寫程式。8 因此,在以 Java 程式語言撰寫程式前,使用者必須先

熟悉 Java 的程式語言本身,進而能以此設計屬於自己的類別,同時,也得學習使

用各種不同的類別庫,才有辦法達到有效的應用。

二、 Java 程式的開發環境

Java 程式的開發需要經過五個階段:編輯(edit)、編譯(compile)、載入(load)、

驗證(verify)以及執行(execute),詳見說明。

(一) 第一階段:建立程式

建立程式所使用的是編輯器程式(editor program)又簡稱為編輯器(editor)

藉由鍵入 Java 程式碼(source code)的方式來編輯檔案。Java 原始碼程式的副檔

名(extension)為「.java」,許多軟體供應商都提供了 IDE 來支援軟體開發,包

括用來撰寫和編輯程式的編輯器,以及找出程式中邏輯錯誤的除錯器。

(二) 第二階段:將 Java 程式編譯為中間碼

在第二階段,程式設計師使用 Javac 指令來編譯程式,即為使用 Java 編譯

器(Java compile)來將原始碼編譯成中間碼(bytecode)。

舉例來說,假如要編譯名為“Music.java”的程式,需要將以下指令“Java

Muisc.java”鍵入到系統的命令視窗,在常用的 Windows 中是命令列提示符號

(Command Prompt),在 Mac OS X 是終端應用視窗(Terminal application),程式

8 Java類別庫又稱做為 Java API(Java Application Programming Interface, Java應用程式

介面),是程式設計師使用(呼叫)的功能性程式,內涵多個函式及指令組合,由於和個別輸

入單一指令是相同的操作方式,對於設計師而言相對方便操作,像是 jMusic 即為一個 Java

API。

Page 23: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

17

編譯過後,編譯器會產生副檔名為“.class”的檔案。以上述例子而言,編譯過

的程式碼將以“Music.class”呈現。

這個階段所產生之中間碼即為第五階段中所要執行的工作。中間碼是以

Java 虛擬機器(Java Virtual Machine, 後文簡稱為 JVM)來執行,JVM 是屬於

JDK 的一部分,9 也是 Java 平台之基礎。虛擬機器(Virtual Machine, 後文簡稱

為 VM)是一種軟體應用程式,可以獨立於作業系統及硬體之外來模擬電腦運

作。因此當一個 VM 實作可以支援多個平台時,那麼藉由此 VM 所能執行的

程式也能在那些平台上使用,也因此使得 JVM 成為目前最廣泛使用的虛擬機

器之一。

但機器語言本身會因為電腦硬體不同而有所差異,唯獨中間碼是獨立於平

台的執行指令,因此可以說,Java 的中間碼具有可攜性,也是使得 Java 語言

可以跨平台使用的原因。

(三) 第三階段:將程式載入

程式執行前需先載入記憶體,以類別載入器(class loader)抓取檔案中內含

“.class”的檔案,並將其轉送至主記憶體中。類別載入器也裝載其他由 Java 程

式提供,在程式內需要的“.class”檔案。載入的途徑可以藉由系統磁碟或網路

兩個管道。

(四) 第四階段:驗證中間碼

在這個階段,藉由「中間碼驗證器」(bytecode verifier)檢查中間碼,確認

檔案沒有違反 Java 安全規定。

(五) 第五階段:執行

9 JDK(Java Develop Kit):Java 開發套件,為昇陽公司針對 Java 開發人員發行的免費

軟體開發套件(Software Develop Kit, 簡稱 SDK)。

Page 24: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

18

以 JVM 執行程式中間碼。現今典型的 JVM 是以「Java 熱點編譯器」(Java

HotSpot compiler)以「直譯和即時編譯」(just-in-time compilation, 簡稱為 JIT)

的方式,分析解釋中間碼並找尋其中常用的熱點(hot spots),最後將中間碼編譯

成低階的機器語言,以加快其處理速度。

上列五個步驟套用到 Eclipse 程式的使用時,簡單的說,當在輸入編寫程式碼

時即為「編輯」階段,而若是在編寫過程中沒有任何錯誤的情況下,當儲存這個

檔案,程式本身就會自動完成「編譯」工作,後續三個步驟則是當使用 Eclipse 中

執行(run)選項時,在無形中自動完成。

三、 Java 程式編寫基本架構與列印字元

Java 語言的指令相當多樣化,基本上而言,Java 語言是一種「物件導向」(Object

oriented)的程式語言。10 以這種語言設計稱為「物件導向程式設計」(Object-Oriented

Programming, 後文簡稱 OOP)。在 Java 設計中,程式設計單元是用來具現化

(instantiate, 即為建立)物件的類別,而類別中包含方法(method, 用來實作運算,類

似 C 語言中的函式)和欄位(field, 用來實作屬性)。

而在編寫 Java 程式之前,首先必須要先分析成品所要達成的需求,進而才能

決定要如何編排程式碼,如何去寫出滿足這些需求的設計。而這種以物件導向的

觀點來分析和設計系統的程序,被稱為是一種物件導向分析與設計成序

(Object-Oriented Analysis and Design, 簡稱為 OOAD),這樣的方式對於程式社記者

而言不僅節省時間,甚至可以減少程式本身的犯錯率。

10

物件導向設計(Object-oriented design, 簡稱 OOD),將相同特徵的物件(object)歸類

為同一類別(class),同時 OOD 也具有繼承(inheritance)這種保有既存類別的特性,進而衍

生加入出自己獨立特性產生成新的物件類別的優點。另外,OOD 會將屬性和運算

(operatrion)封裝(encapsulate)成物件。

Page 25: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

19

(一) 基本架構與列印字元:

在編寫 Java 程式前,先提供 Java 應用程式編寫時類別基礎架構範例(範例

一):

【範例一】Java 應用程式編寫基礎架構

1. public class Classname

2. {

3. public static void main ( String args [ ] )

4. {

5. 程式內容

6. }

7. }

在這個基本的架構中含有幾個重要概念,首先是第一列“public class

ClassName”為一個以 ClassName 為名的類別宣告(class declaration)。每個 Java

程式至少都要包含一個由設計師所設定的類別宣告,這種類別宣告是所謂的

「程式設計師定義類別」(programmer-defined classes)或是「使用者定義類別」

(user-defined classes)。這種類別宣告的開始是由其中的關鍵字 class(class

keyword)引導,關鍵字又被稱為保留字(reserved words)有很多種,但都是由小

寫字母拼成。

後續接著的 ClassName 為類別名稱(class name),類別名稱的第一個字母

都要從大寫開始,但有時類別名稱是由多個字母組成的情況,此時當中的每

個單字的第一個字母也需使用大寫字母(像是例子中的 ClassName)。Java 類別

的名稱是一種識別字頭(identifier),其組成可以是一串字母也可以包含數字或

是底線(_)和金錢符號($),但不能以數字開頭,亦不能包含任何空白字元。另

外,大寫字母除了在類別名稱中特別要求外,在 Java 應用程式的編寫上字母

有大小寫的分別(case sensitive),像 A1 和 a1 兩者就是不同的。

第 3 列的“public static void main ( String args [] )”是所有應用程式的起

Page 26: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

20

點,識別字 main 之後的小括號(parentheses)代表程式的組合區塊,裡面放置的

參數(argument)是告訴電腦該要給這個方法提供哪些型別的資料,整個類別的

宣告也是一種方法(method)的宣告。通常類別的宣告會包含一個或一個以上的

方法,但宣告中含有 main 關鍵字的,在一個 java 應用程式中只能有一個,且

一定要定義否則 JVM 無法執行。關鍵字 void 代表的則是這個方法在執行時不

會回傳資訊。

而方法宣告的主體部分是位於第 4 和 6 列的大括號(})中所輸入的部分,

則是方法宣告的主體部分(body of the method declaration),也就是這個方法具

體的執行方式。同時這裡也提供 Java 應用程式編寫的重要概念:在編寫過程

中有使用到大括號或是小括號都必須要左右成對,否則無法執行。

接著套入架構,命令 Eclipse 執行列印文字“This is beginning!”的指令,如

下列範例(範例二):

【範例二】列印文字範例

1. /* Print Example

2. (1)2 ways print one line

3. (2)Separate in different line

4. */

5.

6. public class PrintExample {

7.

8. // main method begins execution of Java application

9.

10. public static void main(String[] args) {

11.

12. System.out.println( "This is beginning!");

13.

14. /* System.out.println("This is ");

15. System.out.println("beginning!");*/

16.

17. //System.out.println("This\nis\nbeginning!");

18.

19. }

20.

21. }

Page 27: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

21

在這段例子中,第 6 和 10 列的是基本架構中提出的兩個宣告,第十二列

大括號裡面的“System.out.print( "This is beginning!");”為這個方法的主體內

容,使電腦印出雙引號中的字串(string),方法的主體每一個指令都需要加上

分號(;),否則也會被視為一個錯誤。在這道指令中,System.out 是「標準輸出

物件」(standard output object),它允許 Java 應用程式在執行的命令式窗

(comment window)裡顯示字元,而 “.println”即為方法。

同一個例子中還有//和/*兩個符號,雙斜線稱為「單行註解符號」(single-line

comments)或「行末註解符號」(end-of-line comments),使用時是以「// 註解

內容」的方式呈現,代表與此符號在同一列的內容電腦不會執行;而斜線加

上星號稱為「多行註解符號」(multiple-line comments),使用方式為「/*註解

內容*/」,和雙斜線符號類似的情況,只是在這符號間的多列內容會被電腦忽

略不予執行。這類註解的功能,除了方便設計者自己閱讀外,也助於其他人

閱讀並了解程式。

另外,在範例中的第 12 列“System.out.println( "This is beginning!");”和第

14、15 列“System.out.println ( "This is ");”加上“System.out.println ( "beginning!

");”的組合這兩種敘述式的編寫方式,雖然編寫方式不同,但兩者產生的結果

是一樣的,都會列印出"This is beginning!"的結果。同樣是不同的編寫方式,

第 17 列敘述式的“System.out.println("This\nis\nbeginning!");”的情況就和上方

兩種不同,由於中間加入了“\n”為一個換行字元,以至於在後面的字元會回到

下一行的開始處,最終將產生以下結果:

This

is

beginning!

Page 28: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

22

反斜線符號(\)被稱為是逸出字元(escape character),它可以命令 System.out

物件的 println 方法輸出特殊字元(即為例子中接在\n 後方的字元),而這類的逸

出字元加上一個英文字元形成「逸出序列」(escape sequence)的不同有不同用

法,常見的逸出字元如下表(表 3-1-1):

【表 3-1-1】常見的逸出序列

逸 出 字

說明

\n 換行字元。將游標移到下一行起始處。

\t 水平定位鍵。將游標移到下一個定位點。

\r 歸位字元。將游標移回目前該行的開端,後續字元會覆蓋原先顯示字元。

\” 雙引號字元。可以列印出雙引號。

另外,輸出時的方式還有一種為格式化輸出,指令格式為

“System.out.printf(“%s”, “輸出內容”);”,其中的“%s”為一個佔位符號,所謂的

佔位符號是由一個百分比符號加上一個資料型別的英文字母組成,下表(表

3-1-2)列出其中四種:

【表 3-1-2】四種不同佔位符號

Java 符號 名稱

%s 字串的佔位符號

%d 整數資料的佔位符號

%f 浮點數資料的佔位符號

%b 布林值的佔位符號

Page 29: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

23

佔位符號的使用,主要是在輸出內容包含多種型別時,為了簡化並且避

免錯誤,將輸出內容先選擇其中一種型別為主體,其餘的為佔位符號的型式

代替。舉例來說,假如要輸出 “I am 24 years old.”這句話,在輸出時,可以選

擇以字串為主體,分離出整數型別的 24 的方式,寫成 “System.out.printf(”I am

%d years old.”, 24);

”,如此,就能在輸出時避免型別不符而出現錯誤的可能性。這種佔位符

號也能在輸出內容包含多種型別的狀況下使用,能藉此省去針對各種不同型

別個別輸出的繁複手續,改以一次輸出的方式完成。

(二) 基本資料型別(primitive data type):

型別(type)在 Java 這種規類為強調型別語言(strongly typed language)的程

式語言中是一個不可或缺的要素。在 Java 語言的編寫過程當中,若是遇到使

用變數的情況時,對於每個變數都必須加以定義一個型別。而型別的不同,

牽涉到的是電腦記憶體中佔有值的不同,在 Java 語言中有八種基本資料型

別,如下表所表示(表 3-1-3):

Page 30: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

24

【表 3-1-3】八種不同的基本資料型別

關鍵字 型別名稱 記憶體佔用量 範圍

boolean 布林值 8 bits

true 或 false (即 1 或 0,預設為

false)

byte 位元組 8 bits -128~127

char 字元 16 bits 0~65535

short 短整數 16 bits -32768~32767

int 整數 32 bits -(231

)~(231

)-1

long 長整數 64 bits -(263

)~(263

)-1

float 單精度浮點數 32 bits

1.4E-45~3.4E+38

或-1.4E-45~-3.4E+38

double 倍精度浮點數 64 bits

4.9E-324~1.97E+308

或-4.9E-324~-1.97E+308

在過去的 C 語言和 C++語言中,即便是同一種型別,在不同電腦間也不

一定會佔有相同的值,但 Java 語言改善這個缺點,使得同種型別的記憶體佔

有值在任何平台上得以統一;舉例來說,型別中的 int,以往 C 語言和 C++語

言可能在某些電腦佔有 16 位元(即為 2 個位元組),有些則佔有 32 個位元(即

為 4 個位元組),但在 Java 裡,int 的值固定都是 32 個位元。

八種基本型別中,整數類(即 short, int, long)和浮點數類(即 float, double)

在本質上都是整數和浮點數,只是按其位數和佔有位元數的不同而有所差

異。所以,在編寫 Java 程式時,通常整數慣用型別為 int,浮點數慣用型別為

double。

Page 31: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

25

另外,除了上列基本型別外,亦可以依個別需求,在編寫時組合出新的

型別。舉例來說,先宣告一個名為 test 類別:

1. public class test

2. {

3. int i;

4. double j;

5. }

經過宣告,能藉由建立這個 test 類別的物件,形成一個新的資料型別 “test

object = new test();”,這個資料型別的內容包含了一個連續的記憶體空間,如

同宣告中定義的,這個型別的連續空間是由 int 和 double 組合而成。

而除了八種基本型別可以做為新定義型別的基礎外,也能使用自定義的

物件為基礎。以例子 test 做延伸,把 test 物件當作基礎組合,宣告新的 test2

類別:

1. public class test 2

2. {

3. test t;

4. int i;

5. }

同理,在建立新的 test2 類別的物件“test object = new test2();”後,就可以

產生一個包含 test 和 test2 裡面內含的連續空間,也就是形成了含有兩個 int

和一個 double 的新類別。

Page 32: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

26

第二節 Java 語言下的數學與邏輯

一、 Java 中的數學概念

Java 應用程式在編寫時,主要就是一種數學和邏輯推演的概念,所寫出來的

程式內容包含一道又一道的運算式跟邏輯判斷式,交由電腦這個演算工具來做各

種高度精密的運算;像是前文中提及各種 API 中的類別,即是由程式設計師們有

系統的將以數學演算出的概念編寫而成,八種基本資料型別也明顯的反應出 Java

與數學的關連性。

而在以 Java 程式語言編寫數學算式時,也運用下列五種類型的運算子來構成:

(一) 算數運算子(arithmetic operators):

在 Java 程式編寫的過程中所使用的各種運算子,即為在數學中使用的符

號(見表 3-2-1),其中要注意的為除法運算子(/)和餘數運算子(%)功能上的不

同,除法運算子會產生出整數的商,舉例來說,5 / 3 在運算後將會回傳 1;餘

數運算子(亦稱為模數,modulus)是給予兩數相除後的於數值,舉同樣例子,

在 5 % 3 運算過後,電腦將會回傳 2:

【表 3-2-1】各種算數運算子

Java 符號 名稱

+ 加法運算子

- 減法運算子

* 乘法運算子

/ 除法運算子

% 餘數運算子

Page 33: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

27

在編寫各種算式時,都必須要寫成是單行的型式,即為 a + b, a / b 等等,

電腦在運算時將由左到右運行。而運算規則和數學概念相同,乘法、除法和

餘數會先行運算,然後才是加法和減法;假如想要先運算加法和減法部分,

則需要將加法或減法的運算式放在括號之中。

(二) 等號運算子和關係運算子:

條件式的運算式,主要是讓電腦判定其真(true)或偽(flase)。在後面章節

中,將會使用到 if 結構敘述式(if statement),在下表(表 3-2-2)中列出在其中使

用的等號運算子以及關係運算子。

【表 3-2-2】各種等號運算子及關係運算子

Java 符號 範例 名稱

== x==y 等於

!= x!=y 不等於

> x>y 大於

< x<y 小於

>= x>=y 大於等於

<= x<=y 小於等於

雖然說每個的功能都是在於判定是否符合條件式裡的關係,但>=和<=是

只要符合其中一項條件即會回傳為真。

(三) 複合指定運算子(compound assignment operators):

複合型態的運算子是以簡化的方式,縮短指定運算式,第一種類型就是

Page 34: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

28

將原先完整的算數公式予以簡化的方式,只要敘述式符合下列型式:

variable = variable operator expression;

就能簡化成下列型式:

variable operator= expression;

舉例來說:x = x + 2,可以利用加法複合指定運算子轉換成 x += 2 寫法,

如此一來,運算子會將運算子右方的運算數值和左方的變數值相加後,再存

回左方的變數,也就是說即便再例子中看到的是 x = x+2,但就結果而言等號

左方和右方的數值並不相同,這類的運算子由於對應的算數運算子的不同,

也分成五種(見表 3-2-3)。

【表 3-2-3】指定運算子

指定運算子 Java 表式方式 一般表示式

+= x += y x = x+y

-= x -= y x = x-y

*= x *= y x = x*y

/= x /= y x = x/y

%= x %= y x = x%y

另外還有一種運算子可以使得變數的質遞增或遞減 1,這兩種運算子稱做

為遞增運算子(increment operator)和遞減運算子(decrement operator),而這兩種

運算子在使用上又可以各別分成前置遞增和後置遞增以及前置遞減與後置遞

減兩類,如下表(表 3-2-4)所表示。

Page 35: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

29

【表 3-2-4】遞增、遞減運算子

定義 運算子 Java 表示方式

遞增 ++

x++

++ x

遞減 --

x--

-- x

前置與後置的不同,在於前置的++ x 和--x 是在運算式中使用先加過和減

過的新的 x 值,後置的 x++和 x--則是先套用目前 x 的值,然後在進行運算的

動作。

(四) 邏輯運算子:

邏輯運算子在使用上不是用於計算,而是在各種敘述式(像是 if, for, while)

中,將簡單的條件式組合成較複雜的條件式,而這類的運算子有以下六種(見

表 3-2-5):

Page 36: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

30

【表 3-2-5】條件運算子

運算子符號 範例

(假設 x = T, y = F)

結果

條件 AND && x&&y, y&&x

x&&x, y&&y

F, F

T, F

條件 OR || x||y, y||x

x||x, y||y

T, T

T, F

布林邏輯 AND & x&y, y&x

x&x, y&y

F, F

T, F

布林邏輯包含 OR | x|y, y|x

x|x, y|y

T, T

T, F

布林邏輯互斥 OR ^ x^y, y^x

x^x, y^y

T, T

F, F

否定邏輯 ! !x

!y

F

T

就以上範例的結論,在條件 AND 的情況下,比較的值中包含一個偽(錯誤)

即會回傳為偽,反之在條件 OR 的情況下,只要比較的值中包含一個真即為

真;互斥的情況下,兩個比較值為相反為真,相同則為偽,否定邏輯則是將

原先的性質予以否定,產生相反的結果。

Page 37: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

31

二、 Java 語言中的選擇敘述式

Java 語言在編寫中,在許多地方會需要讓程式本身有條件的做出選擇。這類

牽涉選擇邏輯的句子就稱為選擇敘述句(selection statement),這類的選擇敘述句總

共有三種,單一選擇敘述式 (single-selection statement)、雙重選擇敘述式

(double-selection statement)以及多重選擇敘述式(multiple-selection statement)。

在後文各種範例中會使用到資料輸入的方式,將會運用到 Scanner 類別的

API(即為 java.util.Scanner),當在編寫程式碼時,若是需要使用到各種 API,將會

在最開始以 Import 宣告引入類別,以引入 scanner 為範例,必須要在最開始編寫:

import java.util.Scanner;

才能在後文建立物件:

Scanner input = new Scanner( System.in );

當以上兩個步驟完成後,可以藉由執行時輸入不同的數值使程式讀取,以整

數 int 為例,可以用下列方式先假設一個自行輸入的整數變數 a,以下列方式:

int a;

a = input.nextInt();

使得使用者得以用鍵盤輸入對應數值,也可以輸入倍精度浮點數、空白字元

以及字串…等,即為把.nextInt()改成.nextDouble(), .next()以及.nextLine()。

接著是對於單一選擇敘述式、雙重選擇敘述式以及多重選擇敘述式這三種類

別的說明、結構圖以及範例:

(一) 單一選擇敘述式:if

單一選擇敘述式,是使程式能從多種替代方案中選擇一種的方式,主要

結構依照編寫習慣,可以有下表(表 3-2-6)中所列出的三種表現方式:

Page 38: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

32

【表 3-2-6】單一選擇敘述式結構圖

結構一 if ( 布林條件式 )條件為真時執行區段;

結構二 if ( 布林條件式 )

條件為真時執行區段;

結構三 if( 布林條件式 )

{

條件為真時執行區段;

}

以數學的概念來講,單一選擇敘述式用於常見的「當 x 大於等於某數值,

y 則為正數(狀況 a);反之,當 x 小於某數值,y 則為負數(狀況 b)」,這類非 a

即 b 的邏輯概念。

舉例來說,假如以基分 100 為條件,100(含 100)以上即過關,不到 100

則挑戰失敗的概念來寫成敘述式(見範例三)。

【範例三】單一選擇敘述式範例(使用第二種結構編寫)

1. import java.util.Scanner;

2.

3.

4. public class IfExample {

5. public static void main( String args[] )

6. {

7.

8. Scanner input = new Scanner( System.in );

9.

10. int score;

11.

12. System.out.print ( "Enter the score : " );

13. score = input.nextInt();

14.

15. if ( score >= 100 )

16. System.out.println( "Passed" );

17.

18. }

Page 39: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

33

這段程式碼中,單一選擇敘述式的部分為第 15 和 16 列的 if 敘述式,第

15 列的(score >=100)為這個敘述式的條件,第 16 列是使得程式判定若是積分

大於 100 則印出”Passed”的字樣,若未達到條件則不會回報。

前文中提到的 Scanner 類別的建立物件及宣告方法,分別編寫在第 8(建立

物件)、第 10 和第 13 列中(宣告方法)。

(二) 雙重選擇敘述式:if…else

雙重選擇敘述式為單一選擇敘述式的延伸,同為在一個規則下判定結

果。但單一選擇敘述式只可以另程式在滿足條件的情況下給予結果,雙重選

擇敘述式則是把前面文章中提到的「當 x 大於等於某數值,y 則為正數(狀況

a);反之,當 x 小於某數值,y 則為負數(狀況 b)」這種數學邏輯概念的 a 和 b

兩面都表示出來。基本結構有兩種表式方式,如下表(表 3-2-7):

【表 3-2-7】雙重選擇敘述式結構圖

結構一 if ( 布林條件式 )

條件為真時執行區段 ;

esle

條件為假時執行區段 ;

結構二 if ( 布林條件式 )

{

條件為真時執行區段 ;

}

else

{

條件為假時執行區段 ;

}

延續單一選擇敘述式的例子,只要在原先第 15 和 16 列的 if 敘述式後面

加入 else 的條件,如下方範例(範例四):

【範例四】範例三改以 if…else敘述式的方式

15. if ( score >= 100 )

Page 40: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

34

16. System.out.println( "Passed" );

17. else 18. System.out.println( "Failed" );

在這個範例中,if…else 敘述式只在 if 後方設立有條件,else 後方則沒有,

但可以想成在 else 後面接有( score < 100 )這個條件會更容易理解。而這段程式

碼在執行後,在單一條件式時,不回報為滿足條件的情況就會消失,取而代

之的當輸入小於 100 的值會回報”Failed”。

(三) 多重條件敘述式:switch

多重條件敘述式用於根據某一變數,或是某一運算式的可能數值執行不

同的工作。每個工作會和一個整數常數表示式(constant integral expression)相

關。11 Switch 敘述式會判定演算數值與哪一個整數常數表示式相等,進而採

取後續動作,基本結構如下表(表 3-2-8):

【表 3-2-8】多重條件敘述式結構圖

Switch 結構 結構 :

switch ( 控制運算式 )

{

case 整數常數表示式 :

程式區段 ;

break;

case 整數常數表示式 :

程式區段 ;

break;

case 整數常數表示式 :

程式區段 ;

break;

default :

程式區段 ;

break;

}

11

整數常數表示式為型別是 byte, short, int 或是 char 的常數值,但不包含型別 long。

Page 41: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

35

從結構圖中可以看到,每一個表示式都是一個 case,case 和 case 間需要

以 break 分隔,才能使得程式在執行時可以區分每個不同 case 的區段。下面

是延續前面分數範例予不同分數範圍不同等級判定的範例(範例五):

【範例五】多重條件敘述式範例

1. import java.util.Scanner;

2.

3.

4. public class SwitchExample {

5. public static void main( String args[] )

6. {

7.

8. Scanner input = new Scanner( System.in );

9.

10. int score;

11.

12. System.out.print( "Enter the score : " );

13. score = input.nextInt();

14.

15. switch((score-100)/20)

16. {

17.

18. case 5:

19. System.out.print("A");

20. break;

21.

22. case 4:

23. System.out.print("B");

24. break;

25.

26. case 3:

27. System.out.print("C");

28. break;

29.

30. case 2:

31. System.out.print("D");

32. break;

33.

34. case 1:

35. System.out.print("E");

36. break;

37.

38. default:

39. System.out.print("Standerd");

Page 42: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

36

40. break;

41. }

42.

43. }

44.

45. }

如同範例所表示,此switch的控制運算式為第15列switch後方括號內的

(score-100)/20,意即扣除了標準分100後,以20分的範圍為一個等級差距,case

後面銜接的數字即為運算式中的結果數值,以範例而言韻算出來的商為5則會

回報為A,商為4則會回報為B,以此類推。default為首的情形,即為不符合上

述任何一種情況時的所要執行並回報的結果。

在前文中提到以break來做為每個case的區隔,若是在上述範例中把case5

和case4中的break移除,再輸入商為5的數值的情況下,程式將會連續執行兩

個case,並在最後回報AB。

另外除了switch的敘述外,尚能使用if…else這種雙重選擇敘述式串聯的方

式編寫,以範例五為基礎將第15到41列的區塊換成下面範例(範例六)的if…else

程式碼:

【範例六】if…else程式碼替換

15. if ( score >= 200 )

16. System.out.println( "A" );

17. else if ( score >= 180 )

18. System.out.println( "B" );

19. else if ( score >= 160 )

20. System.out.println( "C" );

21. else if ( score >= 140 )

22. System.out.println( "D" );

23. else if (score >=120 )

24. System.out.println( "E" );

25. else 26. System.out.println( "Standard" );

即可得到相同的結果,但此方式相對的必需在每個if後方須重新定義,在

多種情況運用下較為麻煩;優點在於,它可以對應各種算式和規則,不像switch

Page 43: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

37

只能對應在整數常數表示式的情況,在使用的層面上較為廣泛。因此,對於

程式編寫者而言,也必須就方便性及效率考量來決定要使用哪種方式編寫。

三、 Java 語言中的迴圈敘述式

迴圈敘述式(looping statement,亦稱為重複敘述式,repetition statement,或簡

稱為迴圈,loop)在執行時,可以在條件為真的情況下,讓程式本身持續重複動作。

這類的敘述式常用的分成三種:while 迴圈敘述式、for 迴圈敘述式以及 do…

迴圈敘述式,三種敘述式中,while 迴圈敘述式和 do…while 迴圈敘述式兩者本質

上是相同的,只是在編寫時的結構相反,結構如下表(見表 3-2-9):

【表 3-2-9】while 和 do…while迴圈敘述式的結構

while 迴圈敘述式結構 while ( 迴圈繼續條件式 )

{

迴圈主體內容;

}

do…while 迴圈敘述式結構 do

{

迴圈主體內容;

}while(迴圈繼續條件式)

從表中可以看到,兩者的差異在於判斷和執行的先後順序,while 迴圈敘述式

是先判斷才執行,相反的,do…while 迴圈敘述式則為先執行後才判斷;邏輯上相

同的部份是這兩者在編寫時,並無法預期是否會有終點,等同於可能會有無窮迴

圈的可能。說明部分如下列範例(範例七)中表示:

Page 44: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

38

【範例七】while 迴圈敘述式範例

1. public class WhileLoop {

2.

3. public static void main( String args[] )

4. {

5. int number = 1;

6.

7. while ( number <= 100 )

8. {

9. System.out.printf( "%d\n", number );

10. number = number + 2;

11. }

12.

13. }

14. }

此範例要執行的概念,具體來說是要讓程式回報出所有小於 100 的奇數,第 5

列先宣告一個整數 number 是 1,第 7 列 while 後方的小括號中設定了執行繼續條

件為 number <=100,具體執行的內容為第 10 列的 number = number+2,假如換成

do…while 迴圈敘述式的情況就把原先 while 的區塊替換成下列範例(範例八),會得

到相同的結果:

【範例八】do…while迴圈敘述式範例

7. do 8. {

9. System.out.printf( "%d\n", number );

10. number = number + 2;

11. }

12. while( number <= 100 );

這個範例由於在預設條件時是有一個範圍的,所以執行上是有終點的情況。

但若是要改變成是一個無限制迴圈敘述式的情況,只需把條件部分從原先 number

<= 100 改成 number > 0,電腦本身就會就其運算效能回報出無限累加的結果。

for迴圈敘述式和上述while迴圈敘述式及 do…while迴圈敘述式則不同的地方

就在於在設計時,設計者本身已確定有終點,所以在編寫時,除了原先在 while 和

do…while 中的條件式之外,另外還包含了起點和遞增量,其結構為“for ( 初始式;

Page 45: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

39

迴圈繼續條件式; 遞增量 ){迴圈主體內容 ;}”,若是同樣要做成條列出比 100 小的

所有奇數的範例,編寫的邏輯就得改成下列範例(範例九)中的形式:

【範例九】for 迴圈敘述式範例

1. public class ForLoop {

2. public static void main( String args[] )

3. {

4.

5. for(int number = 0; number <= 99; number++){

6. number = number +1;

7. System.out.printf( "%d\n", number);

8.

9. }

10. }

雖然同樣是得到相同結果,但就邏輯上而言,不管在初始值、條件和執行內

容都有些微的落差,之所以有這種差異性是在於,在while和do…while的情形中,

整數number是把初始值和每次運算的結果重複帶入執行的內容去得到結果,但for

的情況則是以小括號中:number從0開始且每次得出number還要遞增1再帶入,最

終number只能在99以下的方式得出結論為1, 3, 5, 7…99的奇數,換言之,for迴圈敘

述式在執行時,每次執行結果都要再次經過遞增量的條件重新帶入,假如把原先

number = number+1換成number = number+2即可看出明顯的差異,在此改變下,回

報數值就會變成2, 5, 8, 11…的等差數列,但實際上條件裡只有設定number+2,於

此,即能看出遞增量對於for敘述式的影響。就結論而言,while和do…while是在判

斷前後都只執行括號內的工作,for則是在每次的執行行為結束後,都會再重新帶

回條件式中判斷。

再用一個更簡單明瞭的範例來解釋,假如執行下方範例(範例十)的程式碼:

【範例十】for迴圈敘述式範例(二)

1. public class ForLoop2 {

2. public static void main( String args[] )

3. {

Page 46: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

40

4. int n = 0;

5.

6. for (n = 0; n < 5; n++)

7. {

8. System.out.println( n ) ;

9. }

10. System.out.println( ) ;

11. System.out.println( n ) ;

12. }

13. }

此範例最終回報出的結果為:0, 1, 2, 3, 4,並在空一列後回報5,於此,能從

範例判讀,即使沒有任何經過運算的過程,每一次在執行迴圈中的指

令”System.out.println( n ) ;”後,都會帶回到for後面條件的遞增量再多加一次運算。

即回報出來的值:0, 1, 2, 3, 4, 5雖然都是n的數值,但0, 1, 2, 3, 4是迴圈內部n

的帶入值,5則是迴圈結束後最後的結果值。若是要解釋其運作的邏輯,必須解釋

為:在回圈內部帶入的值並沒有大於5,可是最終執行5次迴圈過後,4帶入遞增完

後最終值為5。結論為:在小括號中的遞增量,其實可以當作為迴圈執行的倒數第

二個動作,最後一個動作則是使用條件比對條件有沒有成立。

Page 47: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

41

四、 Java 語言中的陣列

陣列是一群包含數值的變數(稱為元素,elements;或稱為分量,component,

後文將以元素稱之),且這些數值都為同一種型別的元素。在型別的分類中,型別

可以分成基本型別和參照型別兩類。而陣列本身屬於參照型別,但其內函的元素

卻有可能是兩者其中的任一種,再要使用陣列中的特定元素時,必須要指出陣列

的參照名稱,以及該元素的位置編號,而元素的位置編號通常被稱為是元素的索

引(index)或是下標(subscript)。

接著第一個步驟是宣告與建立一個空陣列,在宣告一個陣列建立的運算式

(array-creation expression)時,需指名陣列元素的型別以及元素數目,從下面的範例

(範例十一)中:

【範例十一】空陣列宣告範例

int a[];

a = new int [10];

陣列的宣告和前面宣告新的變數或型別時的方式是相同的,都要以關鍵字 new

來建立。在這個範例中,型別是一個整數(int),參照的變數或是這個陣列本身的名

稱為 a,中括號([],square brackets)中的數字代表這個陣列中含有的元素數量(即為

此陣列的大小)。有一個重要的觀念是,每個陣列的第一個元素,在索引時為 0(index

zero),又稱為第零元素(zeroth element)因此在這個陣列中的元素依序為:a[0], a[1],

a[2]…a[9],即索引數為括號中的數減一。

同時陣列宣告的方式也有下列的簡化寫法:

int a[] = new int[10];

假如在編寫程式碼過程中要以陣列中的元素來做運算,在編寫上,就以元素

索引代替元素的值,像是要求其中奇數元素的組合,可以編寫成”sum = a[1]+ a[3]+

Page 48: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

42

a[5]+ a[7]+a[9];”,或者要將其中一個元素做乘法運算,可以寫成”x = a[0]*2”以此

類推。

(一) 空白陣列的使用:

空白陣列的使用情況是,當程式碼太多時,為了方便閱讀,會事先宣告,

並在後面的程式碼終把內容填上。也就是說上述的宣告完之後,空白陣列中

是沒有任何數值的。下面範例(範例十二)是以範例十的宣告為基礎來延伸,先

運用輸出的程式碼,將其索引和值條列出:

【範例十二】範例九索引及數值條列

1. public class Array1 {

2. public static void main( String args[] )

3. {

4. int a[] = new int[10];

5. a = new int[10];

6.

7. System.out.printf("%s%8s\n", "Index", "Value");

8.

9. for(int counter=0; counter< a.length; counter++)

10. System.out.printf("%d%8d\n", counter, a[counter]);

11. }

12. }

輸出的結果會是:

Index Value

0 0

1 0

2 0

3 0

4 0

5 0

6 0

7 0

8 0

9 0

在範例裡,空白陣列的內容是以迴圈的方式處理,只設定條件是要在元

素數量內(counter < a.length),且每次逐漸累加(counter++),下方沒有提供任何

Page 49: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

43

關於數值的條件。但倘若在 for 迴圈下方增加關於數值的條件,譬如說,增加

算式”a[counter]= counter*counter;”,如此一來,輸出的索引和數值將會變成為

索引號的平方:

Index Value

0 0

1 1

2 4

3 9

4 16

5 25

6 36

7 49

8 64

9 81

(二) 陣列初始設定式(Array initializer):

不同於空白陣列的宣告,陣列初始設定式可以將內部元素初始化,意即在

編寫時,可以在一開始定義內容的初始數值,而陣列大小程式本身將會就設定

數值的元素個數自動判定。自定義的元素內容,將會以大括號將由逗號分隔的

運算式(稱做是初值列,initializer list)包覆的方式呈現,像是以下範例(範例十

三):

【範例十三】陣列初始設定式

int a[]= {1,3,5,7,9,11,13,15,17,19};

這段程式碼可以解讀成,此為一奇數組成的陣列,且這個陣列內含 10 個

元素,舉例來說,這個陣列的 a[0]為 1,a[9]為 19,每個相應的數值已給予定

義。而這種方式的宣告就不用關鍵字 new 來定義,且元素的數值也可以是重複

的數字或是多個數字的群組,如同下方範例(範例十四)的表示方式。

【範例十四】陣列初始設定式之數字群組

int a[][]= {{1,3,5},{7,9},{11,13,15,17},{19}};

Page 50: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

44

由多個數字組成群組的情況下,同樣的每個元素也要在以大括號包覆,在

範例十二中,這個陣列的元素個數總共有四個,宣告時用 a[][]方式呈現,之所

以用兩個中括號,是在呼叫陣列中的元素時所需,一個括號是陣列中的第幾個

元素,另一個是該元素中的第幾個元素,也就是說 a[2][2]即為 15。

五、 Java 語言中的數學類別和亂數類別

除了上述幾個基本的運算子跟敘述式外,Java 程式語言數學類別的 API(即為

java.lang.Math)中,也有將一些原先需要經過繁複記算過程才能得到結果的數值,

用簡化後的方法指令來作替代,像是求三角函數的正弦值(sin)、正切值(cos)或是指

數、對數…等等,這一類的方法眾多,在下列表格(表 3-2-10)中僅列出部分較常用

的方法:

Page 51: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

45

【表 3-2-10】數學類別中常用方法

方法 說明

abs(x) 求 x 的絕對值

ceil(x) 求大於 x 的最小整數

floor(x) 求小於 x 的最大整數

cos(x) 求 x 的餘弦函數值(x 為弧度)

sin(x) 求 x 的正弦函數值(x 為弧度)

tan(x) 求 x 的正切函數值(x 為弧度)

exp(x) 取 x 的指數(e^x)

log(x) 取 x 的對數值(基底為 e)

sqrt(x) 取 x 的平方根

pow(x,y) 取 x 的 y次方值

max(x,y) 取較大值

min(x,y) 取較小值

random() 回傳一介於 0.0 到 1.0 間的係數

在這一類的資料型別中,不管輸出和輸入都是 double 型別,宣告的方式以求變

數 x 絕對值變數 f 為例,寫成 “double f = Math.abs( x );”。

另外,數學類別中雖然有亂數的方法“random()”,但它只能對應 double 型別。

因此,假如要遇到要使用亂數指令的情況,Java 程式語言的 API 中也有亂數類

別”java.util.Random”,其用途比起原先數學類別中的亂數更廣泛,涵蓋多種型別,

在後文的音樂創作中,也是一種較常使用的方法,下表(表 3-2-11)列出的也是較

Page 52: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

46

為常用的亂數物件方法:

【表 3-2-11】亂數物件方法

方法 說明

nextBoolean() 傳回隨機 boolean 型別的布林值

nextDouble()

傳回隨機 double 型別的浮點數值

(介於 0.0 到 1.0 之間)

nextFloat()

傳回隨機 float 型別的浮點數值

(介於 0.0 到 1.0 之間)

nextInt() 傳回隨機 int 型別的整數值

nextInt(int n)

傳回隨機 int 型別的整數值

(介於 0 到 n 之間)

nextLong() 傳回隨機 int 型別的長整數值

這類方法的建立有分成兩種,一種是求隨機的亂數,另一種則是求固定的亂

數,在執行亂數類別敘述式之前,必須要以無範圍的“Random randomNumber = new

Random();”;或是以建立固定亂數(seedValue 為 long 型別的數值) 的“Random

randomNumber = new Random( seedValue );”這兩種方式來編寫。

在上述程式碼為先決條件情況下,後方只要用“randomNumber.*”(星號部分可

以使用表 3-2-11 中任一方法),即可以執行亂數指令;但表中“nextInt(int n)”的方法

雖然可以設定上限值,但有些時候在亂數時不僅需要上限值,同時也需要非 0 的

下限值(即負數或 0 以上的數值),因此在這種時候需要加上平移值,以「平移值

+randomNumber. nextInt(縮放比例係數);」的結構來編寫,小括號中所謂的縮放比

Page 53: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

47

例係數,以“randomNumber.nextInt(99);”為例,意思是等同於這個亂數指令將從 0

到 99 之間隨機挑選,但假如在編寫時需要下限值為 10,就必須要在前方加上 10(即

平移值)而變成“10+randomNumber.nextInt(99);”,不過這樣調整後,這道亂數指令

的範圍變成了 10 至 109 之間,上限值會隨之變化,所以若是要將範圍侷限在 10

至 99 的情況,則必須在下限值增加的同時,上限值也隨著減少相同數值,以此為

例子,最終必須要寫成 “10+randomNumber.nextInt(89);”,才會是在提升下限值後,

上限值維持在相同數值的狀態;反之若是在下限值往下調整(即為負數值)的情況

時,上限值若是想維持不變,則需要把減少的值加回來。

Page 54: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

48

第三節 數學概念帶入音樂

在第二節中,使用 Java 語言編寫程式時所需要的基礎邏輯概念,諸如提供條

件的選擇敘述式還是在符合限制條件下使得本身能夠不斷運作的迴圈敘述式等等

都以提供範例與說明,但 Java 語言在使用上,扣除了這些基礎敘述式外,仍有許

多延伸的指令以及更功能多元的各式類別庫,接下來將在本章節中介紹音樂創作

上重點 API “jMusic”裡操作上所需俱備的一些基本概念。

一、 jMusic 中 MIDI 製作相關基礎常用物件名稱

以 jMusic 創作時,整體檔案構成結構和譜面創作時的結構是相同的,在樂譜

(score)底下包含聲部(part),底下一層是樂句(phrase),最小元素為音符(note),如同

下圖(圖 3-3-a)所表示:

【圖 3-3-a】jMusic 創作階層樹狀圖

jMusic 的使用,和使用其他 API 時都必須經過的步驟相同,必須要先編寫引

入指令,而套件位置都是以“jm”為首,而“jm.*”也是其中一類,這一類型的類別庫

則是已經經由程式設計師把一些關鍵字定義過,像是音高、音長等等,其他尚有

六個不同類型的宣告,詳見下表(表 3-3-1):

總譜(包含數個聲部及其之下階層)

聲部(包含數個樂句及其之下階層)

樂句(包含數個音符)

音符

Page 55: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

49

【表 3-3-1】jMusic 中常用的六個不同功能類別庫引入指令

指令 說明

jm.music.data.* 使得檔案得以使用音樂類型數據

jm.music.tools.* 讓使用者可以操作、產生或是編輯 jm 類型檔案

jm.midi.* 使檔案可以讀取或編寫 SMF 類型檔案

jm.midi.events.* 使檔案可以執行 MIDI 類型中的事件,如 NoteOn, NoteOff 等

jm.audio.* 使檔案得以產生、讀取、匯出和編寫 audio 類型檔案

jm.until.* 包含類別中使得檔案得以轉換和修改 jMusic 的檔案

一般而言,大部分的 jMusic 的檔案的引入敘述式至少有下面範例(範例十五)

中的三列:

【範例十五】jMusic 基本引入敘述式

1. import jm.JMC;

2. import jm.music.data.*;

3. import jm.util.*;

有了上列三個引入敘述式後,後面所有編寫程式碼才得以執行,不會有錯誤

產生。接著,以此引入敘述式為基礎,編寫一個單音發聲 A 的範例(範例十六):

【範例十六】jMusic 範例:單音發聲

1. import jm.JMC;

2. import jm.music.data.*;

3. import jm.util.*;

4.

5. public class PracticeMusic1 implements JMC {

6.

7. public static void main(String[] args) {

8.

9. Note n = new Note(A4, 1);

10.

11. Phrase phr = new Phrase();

12. phr.addNote(n);

Page 56: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

50

13.

14. Part p = new Part();

15. p.addPhrase(phr);

16.

17. Score s = new Score("Bing");

18. s.addPart(p);

19.

20. Write.midi(s,"Bing.mid");

21. Play.midi(s);

22. }

23.}

這個範例明顯顯示出圖 3-3-a 階層相扣的概念,各類型的宣告方式和第二章數

學中宣告變數的概念相同,即為使用 “new”關鍵字來做宣告。在本範例中第 5 列

的 “public class PracticeMusic1 implements JMC ”在之後任何使用 jMusic 編寫一

個新的類別時,都需要以 “public class 類別名稱 implements JMC”的格式來編

寫,使得該程式碼能使用 JMC 類別中的物件。其他部分,第 9、11、14 及 17 列

就是對應音符、樂句、聲部以即樂譜名稱的宣告;接續第 12、15、18 和 21 列即

是 使 其 將 前 一 個 階 層 代 入 , 代 入 的 部 分 皆 以 “ 新 的 階

層.addNote/.addPhrase/.addPart(要套用較低階層名稱);”這種型式編寫,只是在音

符、樂句及聲部之間抽換。

(一)音符與樂句-音高的宣告及陣列的應用

在範例十四中另外一個重點是關於音高的宣告,jMusic 對於音符個輸入

結構是以 “Note(pitch, length)”的方式輸入,音高輸入的內容有兩種,一種是

以絕對音名的輸入方式,12 另一種則是以 MIDI 標準音高來輸入。13

以範例

12

絕對音名是以科學音調表示法(scientific pitch notation)這種使用英文字母和數字組

合而成的紀錄法,在這種紀錄法中數字部分為頻率的基頻,舉例來說,和中央 C 同個八

度的高音譜記號的第二間 A 即可標示為 “A4”或是 “A440”。

13 MIDI 標準音高主要是針對絕對音名輸入可能產生的認知上的問題而延伸出來的

紀錄方式。主要是將原先的基頻 f 以 p = 69+12*log2(f/440)這道算式轉化為數字 p 的方

式來表示。這種方法將原先絕對音名隨著高低不同八度調整大小寫字母及數字的

Page 57: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

51

十六的例子而言,音高 “A4”可以替換成 “69”。

而節奏長度在編寫時,也有兩種方式,一種是用英文原文輸入,像是四

分音符即是以“CROTCHET”來表示,若是要用一般英文比較常使用的“Quarter

Note”的說法,則要以 “QUARTER_NOTE”表示,其它還能以縮寫“C”和“QN”

來 替 代 ; 附 點 四 分 音 符 的 寫 法 , 以 “CROTCHET” 為 例 要 改 成

“DOTTED_CROCHET”也可以縮寫成“DC”或“CD”,用“QUARTER_NOTE”的

寫法則要寫成 “DOTTED_QUARTER_NOTE”,縮寫成 “DQN”;三連音的寫

法又有不同,像是常用的八分音符三連音即是以 “QUAVER_TRIPLET”(縮寫

“QT”)或是 “EIGTH_NOTE_TRIPLET”(縮寫“ENT”)表示。另一種是以數字概

念來輸入,在數字輸入法中,數字 “1”代表的即為四分音符,而其他不同的節

奏也是以此為基礎做倍數的轉換。

但音符的定義若是在多個音符和節奏變化的情況下,這種“Note(pitch,

length)”的單音定義方式也將隨之調整,轉換成數學敘述式中陣列的方法來編

寫,而在這種編寫方式下,“Note(pitch, length)”就不在使用,相對的是用 phrase

的方式定義,如同下列範例(範例十七)。

【範例十七】樂句下音高和節奏宣告(範例中音高使用數字輸入,節奏則

為英文縮寫輸入)

int[] pitchArray =

{60,60,60,62,64,64,62,64,65,67,72,72,72,67,67,67,64,64,64,

60,60,60,67,65,64,62,60};

double[] rhythmArray = {C,C,CT,QT,C,CT,QT,CT, QT,M, QT, QT, QT, QT,

QT,

QT, QT, QT, QT, QT, QT, QT, CT, QT, CT, QT,M};

Phrase phr = new Phrase();

表示方法轉成為是一條線性的音高空間,並且以每個八度 12 個音為其差值,舉例

來說,中央“C”在這種數字表示法下即為數字“60”,高一個八度的“C”即以數字“72”

來表示。

Page 58: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

52

phr.addNoteList(pitchArray, rhythmArray);

在 這 種 編 寫 方 式 下 , 音 高 和 節 奏 各 自 形 成 一 個 陣 列 帶 入

“phr.addNoteList(pitchArray, rhythmArray);”這道指令中,但要注意的是以陣列

敘述式在編寫時,在音高和節奏的陣列中的元素數量必須為相同,否則若是

在其中一邊不足的情況下,除了到該處執行會停止外,同時也會回報出現錯

誤。

另外,對於和弦的編寫,在單音發聲的範例十四中,只要分別在音高部

分多宣告其餘兩個音,並在每個類別的帶入中都編寫相應的帶入敘述式即可

使之在同時演奏出和弦音高,而這種編寫概念,和後續將會提到的聲部編寫

概念也有相關。

(二) 聲部的宣告

創作一首作品時,除了基本構成元素節奏、音符外,近一步的,就是配

器上的每個不同聲部的建構,和宣告變數和任何新的元素一樣,聲部的宣告

也需要經過相同步驟,這條敘述式必須包含設定給程式碼讀取的名稱、列印

出的名稱、樂器名稱和第幾軌(channel),如下列結構:

Part 預設讀取用聲部名稱 = new Part(“顯示用聲部名稱”, 樂器名稱, 軌

數);對應這個架構,假定要設定一個長笛聲部就要寫成:

Part Flute = new Part("FL.", FLUTE, 0);

預設讀取用聲部名稱部分是給程式碼也就是電腦讀取時使用,所以和前

文中提到眾多宣告相同,只要方便電腦讀取,這個名稱可以隨著不同需要而

自行設定,列印用聲部名稱是相對於前文中的輸出指令,是在假設有將這個

程式碼轉化成樂譜的狀況下方便辨認使用。

樂器名稱部分,除了需要引入敘述式外,還需要有以“public class 檔案名

Page 59: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

53

稱 implements JMC”的類別宣告為前提(參考前文範例十六中的第 5 列程式

碼),才可以使用該樂器正式的英文大寫原文,否則文字將會無法判讀;另一

種寫法,是以 MIDI 統一規格(General MIDI,簡稱為 GM)中的相應樂器代碼(皆

為整數型別)來編寫,14 這一類的代碼介於 1 到 127 之間,即便不使用類別宣

告也可以使電腦正常讀取該樂器;jMusic 本身也提供了參考用的對照表,方

便程式設計者查閱。

另一個在聲部編寫時重要的觀念是設定聲部加入的時間點以及設定速

度,關於時間的設定要用“*.setStartTime(秒數);”的架構編寫,秒數部分隨著不

同需要,有些情況可以設定到毫秒,所以編寫時都要以帶一位小數的型式編

寫,例如 10 秒是 10.0。而在星號中則以該聲部名稱帶入。定速的情形,主要

是在預設個聲部以不同速度行進的情況下才會需要設定,這種情況和起始時

間設定相同,但改以 “*.setTempo(速度);”的架構編寫。

二、 近代音樂之於 Java 程式語言

(一) 不確定主義程式語言應用:亂數類別

1950 年代左右的美國興起一種新的音樂創作風格,就是由作曲家凱基為

首提倡的一種新概念「不確定主義」,或是更為人所熟知的名稱「機遇音樂」

(Aleatory Music)。這種「隨機」類型的音樂,有三種創作技巧的展現,可以是

單一種,也能是多種同時使用,其三種技巧分別為:(1)在固定作品中,提供

部分隨機的要素、(2)在作曲家規定的範圍內,使得演奏者可以自己選擇要如

14

GM 統一規格是為了在不同 MIDI 儀器轉換間能有一個規範準則,而這個規範使於

1991 年由 MIDI 製造商協會(MIDI Manufacturers Association,簡稱 MMA)和日本 MIDI 標

準委員會(Japan MIDI Standards Committee,簡稱 JMSC)共同制定,有必須要達到以下四個

共同點:(1)須能同時達到 24 個發聲數(包含 16 個旋律及 8 個擊樂聲響)、(2)能表達音符力

度、(3)能同時使用 16 軌音頻、(4)每一音軌的音頻可以發出複音。

Page 60: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

54

何演奏和(3)調整記譜法來減少作曲家對於聲音的控制。三種技巧都提供了演

奏者、聽眾更多的空間,而不似過去受制於樂譜的限制,把所有需要注意的

記號和演奏方式等等全都標示在譜上。

而這類型的音樂,轉化為程式碼的過程也是最為容易的做出來的,因為

單就三項技巧中的「選擇」和「隨機」這兩項,都可以由選擇敘述式和亂數

類別來達成,但是,除了亂數類別的執行出來得到的結果是無法預期的機遇

外,其他諸如選擇敘述式或是亂數敘述式將會得出結果的範圍都是在程式設

計者掌控的範圍之內,機遇本身是以聽眾的角度來預設所得到的最終結果。

下方的範例(範例十八),便是以數學概念下的亂數類別和迴圈敘述式結合所構

成:

【範例十八】亂數類別和迴圈敘述式結合之不確定主義範例

1. import java.util.Random;

2. import jm.music.data.*;

3. import jm.music.tools.*;

4. import jm.JMC;

5. import jm.util.*;

6.

7. public class MusicRandom implements JMC{

8.

9. public static void main(String[] args) {

10.

11. Score s = new Score("Music Random");

12. Part a = new Part("Piano", PIANO,0);

13. Phrase phr1= new Phrase();

14. Random randomNumber= new Random();

15. int[] pitches = new int[10];

16.

17. for(int i = 0; i<10; i++){

18. pitches[i] = 0+ randomNumber.nextInt(127); }

19.

20. double[] rhythmarray ={1, 1, 0.5, 0.5, 1, 1.25, 0.25, 1.25, 0.25, 1};

21. phr1.addNoteList(pitches, rhythmarray);

22. a.addPhrase(phr1);

23. s.addPart(a);

24. Write.midi(s,"MusicRandom.mid");

25. Play.midi(s);

Page 61: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

55

26. View.show(s);

27. }

28.}

在此範例中,最大的重點是對於亂數的使用。首先,在第 15 列先宣告一

個定名為“pitches”內含 10 個元素的整數型別空白陣列,在對應這個空白陣列

中有 10 個元素的情況下,第 17 列的 for 迴圈敘述式括號中也提供了迴圈執行

次數(10 次)的條件,第 18 列的部分則是把條件中的 i 帶入呼叫陣列中的元素,

並且設定執行工作的程式碼“0+ randomNumber.nextInt(127)”,如同在前一節末

的亂數類別說明中提到的,假如在 “randomNumber.nextInt()”的情況下,其亂

數是沒有範圍限制的;在這個範例中,亂數要對應音高的範圍,所以若是在

產生亂數過城中超過上限 127 時,便會因此回報錯誤無法執行;以此為前提

且在“i++”的情況下,這個 for 迴圈敘述式在最後便會執行 10 次的音高亂數,

並在迴圈敘述式外再提供一個節奏陣列使得從迴圈敘述式亂數中得到的結果

能有規則的排列。

除了上述設計內容之外,還有一些程式碼對於使用 jMusic 創作上是非常

方便的,分別是 “Write.midi(score, “名稱 .mid”);”、 “Play.midi(score);”和

“View.show(score);”這三項。從這個範例中可以看到,在第 24 列的

“Write.midi(s,"MusicRandom.mid");”是以 jMusic 創作時要存取 Midi 類型檔案

的必要指令,同時存取的 Midi 檔案也能引入製譜軟體使其轉化成樂譜。第 25

列的 “Play.midi(s);”則是使得該程式碼在執行時得以播放出聲音;第 26 列的

“View.show(score);”指令則是能使得該程式碼在執行時顯示出音高分部圖型的

視窗。

除了上面例子是隨機的音高外,也可以在節奏模式上做到隨機選擇的情

況,在這種情況下,可以使用 switch 或是 if..else 這兩種多重選擇敘述式來編

Page 62: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

56

寫,以下範例(範例十九)便是以 switch 敘述式的寫法來編寫的方式:

【範例十九】隨機亂數節奏組合範例

1. import java.util.Random;

2. import jm.JMC;

3. import jm.music.data.*;

4. import jm.util.*;

5. public final class PatternRhythmRandom1 implements JMC{

6. public static void main(String[] args) {

7. for(short i=0; i<10; i++){

8. Score s = new Score("Random Rhythm");

9. Part p = new Part("Snare", 0);

10. Phrase phr = new Phrase(0.0);

11. int x;

12. double[] pattern = new double[4];

13. double[] pattern0 = {1.0, 0.5, 0.5, 1.0};

14. double[] pattern1 = {1.0, 1.5, 0.5, 1.0};

15. double[] pattern2 = {2.0, 0.5, 0.5, 2.0};

16. double[] pattern3 = {1.5, 0.5, 1.0, 2.0};

17. x = (int)(Math.random()*4);

18. switch (x) {

19. case 0:

20. pattern = pattern0;

21. break;

22. case 1:

23. pattern = pattern1;

24. break;

25. case 2:

26. pattern = pattern2;

27. break;

28. case 3:

29. pattern = pattern3;

30. break;

31. default:

32. System.out.println("Random number out of range"); }

33. for (int j=0; j<pattern.length; j++) {

34. Note n= new Note((int)(38), pattern[j]);

35. phr.addNote(n);}

36. Note m = new Note((int)(49), 4.0);

37. phr.addNote(m);

38. p.addPhrase(phr);

39. s.addPart(p);

40. Write.midi(s, "RandomRhythmPatterns.mid");

41. Play.midi(s);}

42. }

43. }

這段程式碼在第12~16列先宣告一個空白陣列和相應其他四組預設陣

Page 63: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

57

列,然後整個從第7到32列的部分,以一個for迴圈敘述式包含一個switch選擇

敘述式的寫法,switch選擇敘述式是以第17列的" x = (int)(Math.random()*4);"

為條件,讓電腦針對在亂數運算後出來的變數,判定要選擇哪一個節奏組,

同時,由於在範例中變數“x”在設定上為整數型別,但“Math.random()*4”產生

的會是浮點數型別,所以必須要加上“(int)”作為強制轉型的功用;for迴圈敘述

式在本範例中的功能則是設定條件來限定執行次數。

最後一個範例(範例二十)是多聲部的節奏亂數,在這個範例的大部分結構

維持上面範例(範例十九)的大部分內容,變化上是增加幾個新的聲部,聲部起

始時間不同外,其於部分則是使用相同的條件和節奏模組,如下面程式碼所

表示:

【範例二十】多聲部節奏亂數

1. import java.util.Random;

2. import jm.JMC;

3. import jm.music.data.*;

4. import jm.util.*;

5. public final class PatternRhythmRandom1 implements JMC{

6. public static void main(String[] args) {

7. for(short i=0; i<10; i++){

8. Score s = new Score("Random Rhythm");

9. Part p = new Part("Perp.", 0);

10. Phrase phr = new Phrase(0.0);

11. Phrase phr1 = new Phrase(0.25);

12. Phrase phr2 = new Phrase(0.5);

13. int x;

14. double[] pattern = new double[4];

15. double[] pattern0 = {1.0, 0.5, 0.5, 1.0};

16. double[] pattern1 = {1.0, 1.5, 0.5, 1.0};

17. double[] pattern2 = {2.0, 0.5, 0.5, 2.0};

18. double[] pattern3 = {1.5, 0.5, 1.0, 2.0};

19. x = (int)(Math.random()*4);

20. switch (x) {

21. case 0:

22. pattern = pattern0;

23. break;

24. case 1:

25. pattern = pattern1;

Page 64: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

58

26. break;

27. case 2:

28. pattern = pattern2;

29. break;

30. case 3:

31. pattern = pattern3;

32. break;

33. default:

34. System.out.println("Random number out of range"); }

35. for (int j=0; j<pattern.length; j++) {

36. Note n= new Note((int)(38), pattern[j]);

37. phr.addNote(n);

38. Note note = new Note((int)(42), pattern[j]);

39. phr1.addNote(note);

40. Note note1 = new Note((int)(39), pattern[j]);

41. phr2.addNote(note1);}

42. Note m = new Note((int)(49), 4.0);

43. phr.addNote(m);

44. p.addPhrase(phr);

45. p.addPhrase(phr1);

46. p.addPhrase(phr2);

47. s.addPart(p);

48. Write.midi(s, "RandomRhythmPatterns.mid");

49. Play.midi(s);}

50. }

51. }

(二) 極簡主義程式語言化分析

1960 年代的美國,受到凱基提出的機遇音樂所想表達的概念影響,一些

作曲家們也開始思考如何對於前半個世紀在不同主義影響之下發展到過度繁

雜的作品風格予以反動,因應而生出的就是另一種化繁為簡的創作風格-「極

簡主義」(Minimalism, 又稱為低限主義);極簡主義的作曲家有拉蒙德・楊(La

Monte Young, 1935-)、泰瑞・賴利(Terry Riley, 1935-)、史蒂夫・萊赫(Steve

Reich, 1936-, 後文簡稱為萊赫)以及在配樂領域也富有盛名的飛利浦・葛拉斯

(Philip Glass, 1937-, 後文簡稱葛拉斯),發展到後來更進而影響一些歐洲作曲

家,如英國作曲家麥可・尼門(Michael Nyman, 1944-)和愛莎塔尼亞及作曲家

阿莫・培爾特(Arvo Pärt, 1935-)。

Page 65: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

59

極簡主義將創作的元素改成用簡單構成的音高結構、簡單的得節奏以及

微小的節奏變化等等,並且以在多次反覆演奏的過程中設計了微妙的時間

差,使得作品即使是在同樣音高跟節奏組成的情況下,仍可以在音響色彩上

能夠有微妙的變化,簡言之,極簡主義所追求的近似於「同中求異,異中求

同」的精神。

本段將要先以 jMusic 官方也提供的程式語言範例:萊赫的鋼琴的作品《鋼

琴相位》(Piano Phase, 1967)為基礎加以轉化為程式語言的表示方式予以分

析;這首作品由於在編制和音高上較為簡單,因此可以從簡單的程式碼編寫

即可分析,其程式碼的結構詳見下文範例(範例二十一)。

【範例二十一】萊赫《鋼琴相位》程式語言架構

1. import jm.music.data.*;

2. import jm.music.tools.*;

3. import jm.JMC;

4. import jm.util.*;

5. public final class PianoPhase implements JMC{

6. public static void main(String[] args){

7. new PianoPhase(); }

8. public PianoPhase() {

9. Score s = new Score("Piano Phase", 120.0);

10. s.setTimeSignature(6, 8);

11. Part p1 = new Part("Piano1", PIANO, 0);

12. Part p2 = new Part("Piano2", EPIANO, 1);

13. Phrase phr = new Phrase();

14. int[] pitchArray ={E4,FS4,B4,CS5,D5,FS4,E4,CS5,B4,FS4,D5,CS5};

15. double[] rhythmArray =

{0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25};

16. phr.addNoteList(pitchArray, rhythmArray);

17. Phrase phr1 = phr.copy();

18. Phrase phr2 = phr.copy();

19. Phrase phr3 = phr.copy();

20. Mod.repeat(phr, 40);

21. Mod.repeat(phr1, 8);

22. phr1.setStartTime(0.0);

23. Mod.repeat(phr2, 24);

24. phr2.setTempo(120. * (6. * 24.) / (6. * 24. - 1.));

25. System.out.println("End time = " + phr2.getEndTime());

26. Mod.repeat(phr3, 8);

27. phr2.setStartTime(24.0);

Page 66: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

60

28. phr3.setStartTime(32 * 3 - 1);

29. p1.addPhrase(phr);

30. p2.addPhrase(phr1);

31. p2.addPhrase(phr2);

32. p2.addPhrase(phr3);

33. s.addPart(p1);

34. Write.midi(s, "PianoPhase.mid");

35. View.show(s);

36. Play.midi(s);

37.

38. }

39. }

在這段程式碼中,基本部分應用的是前面文章中提及各種的宣告,聲部

的宣告(為範例中第 11 和 12 列)和樂句的宣告(為 13, 17,18 及 19 列)是以基本

型式編寫,唯獨樂譜名稱的宣告(為範例中第 9 列),以“Score score = new

Score("Piano Phase", 120.0);”,名稱的逗點後的數字數值,即為該樂譜基本定

速,拍號的設定 “score.setTimeSignature(6, 8);”(為範例中第 10 列),括號中第

一個數字為拍號中的分子部分,第二個為分母部分。

貫串全曲的音高,如同下方譜例(譜例 3-3-i)所表示,由 12 個音、五個音

高所組成:

【譜例 3-3-i】《鋼琴相位》音高結構

在程式碼的轉換之下,音高在此範例中是絕對音名的型式來表示,因此

形成範例中第 14 列的整數陣列:

int[] pitchArray = {E4,FS4,B4,CS5,D5,FS4,E4,CS5,B4,FS4,D5,CS5};

節奏部分由於都是十六分音符構成,在以四分音符為 1 下換算,十六分

音符為其 1/4 倍,但由於以數字標示方式要換算成小數來表示,所以在這個範

Page 67: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

61

例中將其轉換成 0.25 表示;同時為了對應其小數的數值,型別選擇上就必須

要使用 “double”型別,形成第 15 列的浮點數陣列 “double[]rhythmArray

={0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25}; ”。

另外單獨樂句定速的變化在於本範例中也是兩大重點。速度部分,雖然

在前文中提及在作品名稱定名的同時,可以把作品的基本定速確立,但在本

範例的作品當中,其極簡主義想達到的目的便是隨著樂曲進行聲部會逐漸出

現錯位效果,因此在這個範例中的第 24 列,便是對於營造此效果而特別對於

第三樂句的速度變化設計,程式碼 “phrase3.setTempo(120. * (6. * 24.) / (6. * 24.

- 1.));”中,可以看到對於速度部分,在後方的小括號提供一道運算方式來給予

速度變化的條件(變快或慢,以及其速度變化的幅度)。在這個範例的條件中,

120 是一開始確立的基本定速,6 為在此範例中每個小節含有的拍數,24 則是

第三樂句的反覆次數(參考第 23 列的部分),但若根據所希望變化幅度的差別

的不同,也可以調整基礎速度以外的數值。

最後針對所有 jMusic 創作都通用的,在範例中還有一個重點是在於

“Mod.*”類別的使用,“Mod.*”類別的敘述式是屬於“jm.music.tools.*”的一部

分,內含的所有功能(像是作曲技法中的倒影、逆行等等)都是作為修改基本

jMusic 的型別所用。“Mod.*”敘述式在範例中使用的功能是「反覆」(為範例中

第 20, 21, 23 和 26 列),以第 20 列的 “Mod.repeat(phrase1, 40);”為例子,括號

內逗點之前是編寫將要反覆的樂句,數字部分則預設該樂句的反覆次數。

(三) 數學理論之於音高排列應用:正弦波(Sinewave)和音雲(Sound Cloud)

在前文中,不確定主義利用了數學類別中的亂數和數學邏輯中的選擇概

念,而極簡主義則是以陣列分組並且做出時間差的規劃。在節奏上,兩者都

Page 68: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

62

能明確的給予排列或是排列出多種給予選擇;反之,在音高設定上,雖然亂

數類別可以劃定出一個具體範圍,但卻缺少對於音樂方向性上明確的指令,

而低限主義本身卻也因為音高構成簡化構成其音樂的方向性是維持在持平的

狀態。

因此在本章節的最後,將以數學上每個人都熟悉的直角座標圖的概念,

來具體說明如何以數學上各種方程式和算式來形成音樂方向性的線性排列;

以及同樣是以圖型概念來編寫,卻能呈現多元性質排列的音雲。

在這種以數學概念來規劃音高排列和方向性時,主要考量的因素是想要

如何構圖,因為構圖的方式牽涉到該要設計怎樣的方程式去達成。這種構圖

的方式,是由許多的音符串連而成,但音符的多寡也是可以藉由自訂其密度

(density)等要素來規範,以下範例(範例二十二)是使用數學概念中的正弦波的

概念來構圖:

【範例二十二】音高以正弦波構圖排列之程式碼

1. import jm.JMC;

2. import jm.music.data.*;

3. import jm.util.*;

4.

5. public class MusicSample2 implements JMC{

6. public void main(String[] args){

7. Score s = new Score("SineMelody");

8. Part p = new Part("Melody", PIANO, 0);

9. Phrase phr = new Phrase();

10. double density = 20.0;

11. for(int i=0; i<(2*3.14*density); i++){

12. int pitch = (int)(Math.sin(i/density)*50+60);

13. Note n = new Note(pitch, DSQ);

14. phr.addNote(n)}

15. p.addPhrase(phr);

16. s.addPart(p);

Page 69: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

63

17. View.show(s);

18. Play.midi(s);

19. View.show(s);

20. Write.midi(s, "SineMelody.mid");

21. }

22.}

這段程式碼的音高構圖,藉由第 17 列的“View.show(s);”將會得到其音高

排列的圖形,如同下圖(圖 3-3-b):

【圖 3-3-b】範例二十二執行後音高表示圖

這個圖形構成的主要依據,就是三角函數中的正弦和餘弦定理下,

f(x)=sin(x)和 f(x)=cos(x)在平面直角座標圖上會呈現一個波狀的圖樣。而這個

定理反應在第 11 到 14 列的 for 迴圈敘述式的區塊中,主要的核心方程式為第

12 列的“int pitch = (int)(Math.sin(i/density)*50+60);”,在這道方程式中由密度

和“i”兩個變數決定圖型,密度的數值在第 10 列的時候已經是先預設好,當密

度值數值越大時,構成線狀的音符也越多,圖形也越完整,相反的,當數字

越小時,其構成的音符也越少,圖型也就越不完整;而這個範例中的密度值

Page 70: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

64

也牽涉到在 for 迴圈敘述式的小括號中附予變數“i”的迴圈條件所得到結果的

數值,也影響到最後圖型中所呈現的週期大小。

另 外 影 響 到 音 高 的 核 心 方 程 式 “int pitch =

(int)(Math.sin(i/density)*50+60);”中的“(Math.sin(i/density)*50+60);”,可以將它

看成是數學中的“50sin(x)+60”,所加上的數(為算式中“60”)代表了偏移後的起

始點,化作音高的話相當於中央“C”,調整數值的話也就等同於調整起始音

高;乘上的數值(為算式中“50”)影響了整個圖型的振幅,也就意味著在本範例

中,產生出的音高最高和最低音差距為 100(最高音為 “110”最低音為“10”),

這兩個數值可以就需要自行調整,但由於是在音高的情況下,其值必須要在 0

到 127 之間。

接著是分散塊狀的音高編排-音雲的程式碼編寫,音雲的編寫相當於是前

文基預音樂中提到的亂數類別應用,只是在編寫過程中,除了原先執行亂數

的指令外,在此又多考量了織度(texture)的密度要素在,如同下列範例(範例二

十三)所表示:

【範例二十三】音雲程式碼編寫範例

1. import java.util.Random;

2. import jm.JMC;

3. import jm.music.data.*;

4. import jm.util.*;

5.

6. public class SoundCloud implements JMC{

7. public static void main(String[] args){

8. double cloudDensity = 0.1;

9. Phrase phr = new Phrase();

10. Random randomNumber= new Random();

11. for(int i = 0; i < 3000; i++) {

12. int Pitch = 55+randomNumber.nextInt(67);

13. double rv = Math.random() * cloudDensity;

14. int rDyn = (int)(Math.random()*127);

15. phr.addNote(new Note(Pitch, rv, rDyn));

16. }

Page 71: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

65

17. Part p = new Part("SoundCloud", VIOLIN, 0);

18. p.addPhrase(phr);

19. Score s = new Score(p);

20. View.show(s);

21. Write.midi(s, "SoundCLoud.mid");

22. Play.midi(s);

23. }

24. }

這段程式碼的主要執行部分也是以 for 迴圈敘述式為主軸,並且在當中同

時使用了數學類別中的亂數方法和亂數類別,使用數學類別的亂數方法的原

因在於它的亂數範圍僅限在 0 到 1 間,就本範例中第 13 列的節奏(0 為沒有聲

音)和第 14 列的力度(範圍從 0 到 127 之間)所得到的計算結果可以適用,而亂

數類別在本範例是因為它可以界定範圍,適用於使用樂器有音域限制的情

況;而 for 的迴圈敘述式在這個範例中相當於時間長度,條件中的變數“i”的大

小即為最終執行後產生的音符數,而密度的設定對於這個範例而言,主導了

節奏亂數出的結果,不同於在機遇的選擇節奏模組,範例中最後產生的節奏

會因為亂數出的結果造成疏密或是休止的變化,而本程式碼執行最後所呈現

出來的圖形如下圖(圖 3-3-c)所表示:

【圖 3-3-c】範例二十三執行後音高表示圖

Page 72: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

66

最後,對於電腦音樂創作上的構圖而言,雖然可以用各種算式達到不同

的呈結果,但音樂相關的部分數值限制也要在編寫時一同考量進去算式當

中,例如音高和力度的數值範圍就是必須注意的項目;另外,由於數學類型

中的亂數類別產生的質屬於浮點數型別,不像亂數類別可以自行定義需要的

型別和範圍,在使用上就要多加注意是否需要多一個強制轉型的步驟。

Page 73: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

67

第四章 作品分析,作品《幻實之鏡》

第一節 創作概念

在創作之初,對於筆者而言,從事電腦音樂類型的創作也是第一次嘗試,再

加上以 Eclipse 這種媒介創作方式,目前在國內尚未有人使用,因此本作品將是以

實驗性作品的前提來創作,換言之,想達成的主要目的有兩個,一是如何把電腦

音樂元素做妥善的運用,二是以本作品做為範例的衍生說明。

但在達到第一個目的前,也面臨了一個問題,電腦音樂在創作上仍舊擺脫不

了的一大缺點就是容易失真,即便在科技如此發達的現在,以電腦合成模仿出來

聲音在多數人耳中仍是能輕易分辨其真偽;同時,受制於在作品中著重的是 MIDI

的型態做最初的檔案製作,在音質上更是受到了電腦效能和播放硬體的影響,為

了彌補這項缺點,最終才決定以現場演奏搭配電子構成音效的方式來作為本作品

的表現方式。

《幻實之鏡》一名也隨著這樣的概念而確立,其意義就在於,「像」是由鏡子

所產生,在鏡子這項媒介的兩端,實像與虛像彼此交錯、相輔相成。聲音也是相

同,幻的意義是抽像、不實在的,如同電腦所產生的聲響般,實則是現場演奏的

樂器所產生之聲響;整首作品聲部關係的構成,時以電腦與現場兩者交錯互相競

逐、時以兩者同時並存營造氛圍等方式處理;聲響的構成上,儘管前文中提及電

腦音樂在聲響上有缺點,但本作品也基於這點做延伸,要的是電腦最終產生的不

Page 74: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

68

真實音響。而現場演奏部分選擇小提琴獨奏,選擇小提琴有兩個主要原因,第一

是比起其他大多數管擊樂而言,弦樂器不僅音域廣泛,也較不易受制於技術層面

或是由樂器結構等因素影響,造成某些音區上聲音較不穩定,甚至有極限;雖然

弦樂器同樣都具有音域廣泛的優勢,但其中小提琴儘管在低音音域的廣度略顯不

足,卻在中音音域及高音音域的部分,具有良好的發聲品質以及穿透力。

第二個原因是聲音變化多樣性。小提琴由於其演奏技法多元,音色的變化性

以及彈性比起大部分樂器要多出許多,諸如左手能操作的左手撥弦、泛音等等;

而右手技巧部分更是不勝枚舉,不管是拋弓、跳弓、頓弓等或是在弓法或是演奏

力度上的些微變化都可以造成不同的音色的呈現。同時,因應從二十世紀初到現

今這近百年的時間裡,大量的近代音樂及現代音樂的作品,都為了替這樣樂器找

到更多不同於以往的發聲方式創做了許多實驗性的技巧,也使得弦樂器演奏技法

除了傳統的拉奏與撥弦外,有更多發展上的突破。

創作概念上,整首作品可以分成五個段落,每一段落分別代表不同情境、主

題,段落長度約 1 分鐘左右,整體作品運作上,是以電腦構圖及其產生的聲響為

主軸。內容所使用的程式碼,大多將是在前面章節中提過的各式選擇敘述式、迴

圈敘述式以及邏輯運算子、構圖上的正弦波及音雲等概念為基礎,同時融入了在

jMusic 一節中提到有關音樂史中的不確定主義、極簡主義,以達到多重元素串聯

的目的,形成一首範本型式的實驗作品。

而現場演奏部分,為了配合電腦操作中的機遇要素,在本作品中將會有不予

記譜的呈現方式,讓演奏者隨著演出當下所聽到的電腦音效即興演奏配合,使得

本作品最終會隨著演奏者的感受不同而達到不同的結果,也使得整個作品都和機

遇音樂的理念緊緊相扣。

Page 75: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

69

第二節 創作歷程

構想這首作品時,誠如在第一節中所提到的,在實驗性創作為前提下,該要

怎麼組織出一首完整作品?第一點考量到是電腦特性,也就是快速的及時演算能

力,就這個特性,最初想嘗試以及時輸入讓電腦演算的方式來呈現,但礙於大多

數電腦在效能上能負荷的極限不同,因此在做了諸多嘗試後,最終決定將一首完

整作品作多個段落的分開製作,使得即便在不同的硬體設備下也有可能正常操作。

第二點是該要如何構圖,構圖也是整體創作中最為麻煩的一個步驟,首先必

須要先選擇要使用哪些方程式,方程式中的數值也受到力度、音高等 MIDI 中所有

參數的範圍限制(最大值為 127),使得在執行時需要反覆檢視,在最不影響執行效

果的情況下提供相應條件,在此不影響執行效果所牽涉到的要素也有很多,以在

迴圈敘述式中最為常見的問題是迴圈執行次數,在 MIDI 參數的範圍限制下,同時

又必須要兼顧到音符密度和想要執行時間的長度影響,在希望同時兼具速度快、

音符密高執行時間又長的情況下,很容易就會出現超出範圍的情況,使得整個程

式出現錯誤無法執行,而編寫時由於 jMusic 中每個 API 所含的敘述式數量龐大,

除了一邊熟悉之外,同時也不時的參照以找尋所需的 jMusic 類別。

同樣在構圖上另一個要考量的要素是關於時間精算,這類問題主要發生在呈

現效果的段落,在 jMusic 中節奏長度值最短相當於是記譜中 32 分音符的長度(也

就是在 1 為四分音符情況下的 0.125),因此在譬如說速度極度快 (像是以一拍等於

1000 的情況下)和音符極高密度的情況下,即使知道執行次數,但實際上的時間,

還有多聲部哪個聲部要多久進來或是要多久漸強漸弱等都是需要反覆嘗試的調整

Page 76: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

70

數質。

第三點是關於演奏技法的呈現,儘管 jMusic 在音樂創作上已經具備一定程度

所需的程式碼,但在呈現一些特殊技巧上,譬如說像是滑音(Glizzando)的效果時,

並沒有一個特定的指令是可以使其做出該效果,因此在這些情況就要思考如何用

正常的程式碼方來寫出想要表達的效果和演奏法,像是想要減少音的顆粒使其更

加圓滑可能要用調整速度和節奏、增加密度的方式來達成,也是在創作過程中面

臨到的問題。

最後在創作過程中要考量的要素是如何結合現場樂器的演出?以沒有極限的

電腦和有極限的人類演奏所組合的情況下,樂器能模仿到什麼程度?演奏者能達

到最高限度的速度或是力度在哪?交織過程中的容錯率和配合的時間差還有在兩

者間聲響反差甚大的情況下要怎麼選擇好的音效?如何想像出聲響整體感?等等

都是不同於以往在寫出樂譜的情況,多了許多部分是藉由構圖來想像,同時猜測

可能的結果,像是在配合儘管有設下相當條件卻仍隨著每次亂數而有不同結果的

電腦聲部,現場演奏聲部會如何隨機詮釋,這些都是機遇要素下,那些不確定的

因子,也都是演出時可能會出現變化的變因,全盤考量的結果,許多環節上都需

要一再調整和反覆審視才能完成最終的作品。

Page 77: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

71

第三節 作品分析

本節分析筆者以 jMusic 的各式為題材之作品《幻實之鏡》,主要可以分成五個

段落,在這五個段落中筆者運用了不同的電腦線條構圖,使樂曲呈現不同層次的

意境,以密度變化、聲部間音域區塊移動並且以多聲部疊合產生聲響衝突的方式,

找尋電腦與現場演奏的平衡。

電腦部分,在聲部線條數量多為三至四條共構,有時是和現場演奏聲部相呼

應,有時則產生互相疊合聲響區塊,譬如說正弦波和音雲的疊合衝突;小提琴聲

部在各段落扮演角色各不相同,有時是作為引導用途,有時則融入電腦聲部的交

織中。

第一個段落為《序》,想呈現的是由現場演奏和電腦交錯互動的一種表現方

式。音域上,電腦和小提琴兩個聲部都設定由低音開始,並以小提琴半音音型做

為主導,再一次次的反覆中,逐漸延伸把音域拉寬。電腦聲部程式碼如下方範例(範

例二十四):

【範例二十四】作品《幻實之鏡》第一段落程式碼

1. import java.util.Random;

2. import jm.JMC;

3. import jm.music.data.*;

4. import jm.util.*;

5. import java.lang.Math;

6. import jm.music.tools.*;

7. public class TC3 implements JMC {

8.

9. public static void main(String[] args) {

10. Score s = new Score("TC");

11. s.setTimeSignature(4,4);

12. s.setTempo(40.0);

13. Part p1= new Part("Wind Effect", WIND,0);

14. Part p2= new Part("TS",44,1);

15. Part p3= new Part("TS2",44,2);

16. Part p4= new Part("Slap",SLAP,3);

Page 78: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

72

17. Phrase phr1 = new Phrase();

18. Phrase phr2 = new Phrase();

19. Phrase phr3 = new Phrase();

20. Phrase phr4 = new Phrase();

21. phr2.setStartTime(20.0);

22. phr3.setStartTime(28.0);

23. phr4.setStartTime(28.0);

24. int [] pitcharray = {0, 35, 0, 35, 0,35};

25. double [] rhythmarray = {0.0, DHN, 0.0, DHN,0.0, 7.0};

26. phr1.addNoteList(pitcharray, rhythmarray);

27. Mod.repeat(phr1,2);

28. Note n = new Note(35,12);

29. phr1.addNote(n);

30. Mod.decrescendo(phr1, 23.0,50.0,60,40);

31.

32. for(int i=0; i<127; i++){

33. int pitch= j;

34. Note n1= new Note(pitch, 0.0625,60);

35. Mod.crescendo(phr2, 20.0, 35.0, 60, 80);

36. phr2.addNote(n1);

37. Note n2 = new Note (127, 0.0625,60);

38. phr3.addNote(n2);

39. Mod.decrescendo(phr3, 35.0, 55.0,60,30);}

40.

41. double cloudDensity1 = 0.01;

42. Random randomNumber= new Random();

43.

44. for(int j = 0; j < 2000; j++) {

45. int pitch1 = 60+randomNumber.nextInt(67);

46. double rv = Math.random() * cloudDensity1;

47. int rDyn = (int)(Math.random()*127);

48. phr4.addNote(new Note(pitch1, rv, rDyn));}

49.

50. int u =20;

51. int n1 = 100;

52. double density = 0.001;

53.

54. for(int k=500; k>0; k--){

55. if( k%5==0) n1--;

56. if(k%25==0)u--;

57. int pitch2= (int)Math.abs((Math.sin(k / density) * u + n1));

58. Note n3= new Note(pitch2, 0.01,60);

59. Mod.crescendo(phr2, 55.0, 60.0, 60, 10);

60. phr4.addNote(n3);}

61.

62. p1.addPhrase(phr1);

63. p2.addPhrase(phr2);

64. p3.addPhrase(phr3);

65. p4.addPhrase(phr4);

66. s.addPart(p1);

Page 79: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

73

67. s.addPart(p2);

68. s.addPart(p3);

69. s.addPart(p4);

70. Write.midi(s, "TC.mid");

71. View.show(s);

72. Play.midi(s);

73. }

74. }

這個段落的電腦聲部中主要有三個線條(其中 p2 和 p3 為同一聲部及其延伸),

各線條分別是:p1 為風聲效果,p2 和 p3 為弦樂的顫音(Tremolo)演奏效果,p4 則

為拍板。使用的構圖方式,p1 是以陣列方式編寫,主要是為了因應同時有不同節

奏和休止的情況。

p2(p3)和 p4 則是以 for 迴圈敘述式的方式編寫,但儘管都是用 for 迴圈敘述式,

卻隨著執行內容的不同有著不同的功能。在包含 p2 和 p3 的 for 迴圈敘述式裡,這

個迴圈的條件對於 p2 相當於是音高的拔升,可以看到條件裡的 i 值從最小值 0 的

無聲狀態到最大值 127;p3 在其中的功能是為了要延伸出最高音,迴圈的執行次

數相當於是它的長度。

p4 中包含的前後兩個迴圈,分別為在第三章中的最後說明的音雲和正弦波的

應用,前半段音雲部分是做為散射點狀的音符,使之不時和 p3 延伸高音撞擊產生

衝突聲響;後半段的密集正弦波擇是承接原來 p3 的高音,並以波動幅度逐漸減少

的方式,將音高帶回極低音,做為一下段落的銜接,而整個段落的音高構圖如下

方電腦截圖(圖 4-3-a)。

Page 80: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

74

【圖 4-3-a】作品《幻實之鏡》第一段落《序》音高構成分布圖

p1 聲部為下方長短不一的虛線狀圖型,p2 聲部則為圖中由左下至右上的灰黑

色同時以實線和虛線構成的圖形,p3 聲部為接近視窗頂部的墨綠色橫線,p4 的音

雲為下方的方型散狀音符區塊,正弦波則為接續著的左上至右下斜向的逐漸轉為

集中的斜線。

在本段落的小提琴聲部的音型如下方譜例(譜例 4-3-i),從一開始的十六分音

符、第二次的五連音到最後從五連音延伸拉長的線條,以此預示後方電腦聲部即

將拔升的音高,此外,小提琴的音符和電腦聲部中 p1 的間隔為相互填補關係。

【譜例 4-3-i】作品《幻實之鏡》第一段落《序》小提琴聲部引導音型及延伸

隨著兩次模進到了電腦聲部 p3、p4 並存時,由於 p3 和 p4 兩個聲部的聲響效

果皆為點狀的,因此小提琴聲部在這個部份的設定,是以近橋奏(sul punt.) 的效

Page 81: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

75

果、不定速的滑音音型以及同 p3 為顫音的演奏技巧做為呈現,如下方譜例(譜例

4-3-ii)。

在此雖然同樣為顫音效果,但實際演奏時將會以高密度的方式演奏,使之同

時兼具點狀和線狀的效果,並且滑奏的頻率隨著時間也會越來越頻繁,以此表現

所謂實像的顫音與代表虛像的電腦顫音做疊合。

【譜例 4-3-ii】作品《幻實之鏡》第一段落《序》小提琴滑奏記譜

第二個段落為《詭譎》,試想以電腦多聲部間聲響激烈碰撞來表現這個氛圍。

電腦聲部的聲部構圖部分,將同時以三條不同方向和週期的正弦波交錯,並且將

三條正弦波的起點分別設定在低、中、高三個音域,到了三個線條密集疊合時,

又以將原方程式逆向操作的方式,讓三條正弦波反折,形成一個對稱的鏡像。本

段落的呈現將單純以電腦播放聲響為主,使其在三個聲部疊合階段的衝突聲響能

更清晰,而三個音域的線條分別為:上往下的是風聲效果、下往上的為鋼鼓、中

間橫向為鳥叫聲效果,其音高分布圖如下方表示(圖 4-3-b):

Page 82: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

76

【圖 4-3-b】作品《幻實之鏡》第二段落《詭譎》音高構成分布圖

然而,雖然程式碼編寫上依然是用正弦波的組合,但卻因為定速的不同,使

得本來會是規則且波動型狀較為顯著的如同圖 3-3-b 的正弦波構圖,變成在本段落

中近似為是以音雲的構圖狀態。

同時,因為設定數質的不同,使得原先應是水平開展的正弦波,變成斜向且

逐漸擴增的狀態,更進一步的,設定數質的不同也影響了起使點,使之分為兩個

上下相對正弦波和一個橫向較為鬆散的正弦波,主要架構如同在第三章中說明過

的,但圖 4-3-b 中較為特別的是在於上下兩端有虛線般的點狀音高分佈,造成這樣

的分部主要是由於對於中央橫向正弦波所附加的條件,如同下列範例(範例二十

五):

【範例二十五】第二段落《詭譎》中聲部程式碼前區段

1. double density2=10.0;

2. int j = 10;

3. for(int i = 0; i < 1600; i++) {

4. int pitch2 = (int) Math.abs((Math.sin(i/density2) * j + 60 ));

5. if (i%50==0) j++;

6. if (pitch2 >127) pitch2=127;

7. if (pitch2 < 0 ) pitch2=0;

Page 83: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

77

8. if(pitch2 >=90) pitch2=120;

9. if(pitch2<=40)pitch2=30;

10. Note note2 = new Note(pitch2, DSN,10);

11. phr2.addNote(note2);

12. Mod.crescendo(phr2, 45, 530, 10, 90);}

排除掉迴圈敘述式中大部分正弦波敘述式的話,可以在第 5 到 9 列看到 if 選

擇敘述式,第 5 列的作用是對於 for 迴圈敘述式的條件再加一個附加條件,使得第

四列方程式中的變數 j 能夠逐漸增大。第 6 和第 7 兩列敘述式分別是針對音高範圍

設下限制,使得即使在迴圈最後出現超過 MIDI 範圍上下限的情況時,音高仍能保

持在極限值;而影響圖中點狀音高分布的主要敘述式為範例中的第 8 及第 9 兩列,

在此的條件為當達到特定音高時,在這個界限音高之上或之下的音高會固定在某

個單一音高中,可以視為是第 6 和第 7 兩列的應用。

第三個部分的主題是《違和》,想呈現為電腦和現場演奏聲音彼此融合的氛

圍。聲部構圖是以極簡主義為主要風格,音高線條構成方式依然是以正弦波的方

程式構成,聲部數量搭配現場演奏的小提琴聲部總共有三個,為兩部小提琴(即電

腦加上現場小提琴)再搭配電腦的中提琴聲響的組合,形成一個三重奏型式的極簡

主義段落。

構成這個部分的核心程式碼也是以 for 迴圈敘述式串聯,使音高不停循環反

覆,其主要核心的 for 迴圈區塊如下方範例(範例二十六)表示:

【範例二十六】作品《幻實之鏡》第三段落《違和》核心 for 迴圈敘述式程式碼

1. for (int i = 10; i < 400; i++) {

2. double density= 1.0;

3. int pitch = 0;

4. if (i % 2 == 0) {

5. pitch = (int) (Math.sin(i/density ) * -5 + 80);

6. } else if (i % 3 == 0) {

7. pitch = (int) (Math.sin(i/density ) * 10 + 80);

8. }else if(i%4==0){

9. pitch = (int) (Math.sin(i/density ) * 15 + 80);

10. }else{

Page 84: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

78

11. pitch = (int) (Math.sin(i/density ) * -20 + 80);

12. }

13. if (pitch < 55)

14. pitch = 55;

15. if (pitch > 85)

16. pitch = 85;

17. Note n = new Note(pitch, 0.25);

18. phr.addNote(n);}

在範例中能看到許多 if 條件敘述式與 else…if 條件敘述式的串聯,這種設定是

延伸自第二部分對音高限制範圍的做法,使得每執行一次迴圈就會比對定義的條

件選擇出相應的正弦方程式;而這種多重條件的設定方式,主要是對應以方程式

為基礎構圖的情況,由於方程式構圖會使音高排列具有規則性,所以為了打破規

則的循環,因此在條件越嚴苛的情況,構圖也會隨之扭曲。本範例中即可看到有

四種正弦波算式的選擇,分別為第 5 列的“pitch = (int) (Math.sin(i/density ) * -5 +

80);”、第7列的 “pitch = (int) (Math.sin(i/density ) * 10 + 80);”、第 9列的“pitch = (int)

(Math.sin(i/density ) * 15 + 80);”以及第 11 列的“pitch = (int) (Math.sin(i/density ) *

-20 + 80);”,使之最終三個聲部將產生以下的音高構圖(圖 4-3-c)。

【圖 4-3-c】作品《幻實之鏡》第三段落《違和》音高構成分布圖

Page 85: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

79

另外本段落中現場演奏的演奏者所閱讀的樂譜即是以上方的音高排列構圖下

藉由製譜軟體產生,使得最終呈現時三個聲部是基於相同的音高、節奏結構融合

在一起,這種方式想呈現的是不同於第二部分的電子聲響衝突,改以表現電子生

想與即時演奏聲響的音響色彩變化。

第四部分是《幻》,這個段落著重的是 jMusic 音色選擇和應用,使得整體氛圍

彷彿重現自然的景像。創作風格上是基於不確定主義的想法,使得不論是電腦聲

響還是現場演出都是出自於機遇,音色選擇上,一樣是由三條線條共構,分別為

「鳥聲」、「風聲」以及「冰雨」。三個聲部都是由一個相同的程式碼產生結果,程

式碼構成如同下方範例(範例二十七):

【範例二十七】作品《幻實之鏡》第四段落《幻》核心程式碼

1. for( int i=0; i<400; i++){

2. int a = 0;

3. if ( i % 2 == 0){

4. a = 90;

5. }else if( i % 3 == 0){

6. a = 30;

7. }else if( i % 4 == 0){

8. a = 127;

9. }else{

10. a = 60;

11. int pitch = (int)(Math.sin(i/1+randomNumber.nextInt(a-1)) * 10 +60);

12. if (pitch < 0) pitch=0;

13.

14. double rhythm = 0.0;

15. rhythm = (randomNumber.nextDouble())*(randomNumber.nextInt(100));

16. if (rhythm > 2.0)rhythm = 2.0;

17. if (rhythm < 0.0)rhythm=0.0;

18. int dyn = (int)(Math.random()*127);

19. phr.addNote(new Note(pitch, rhythm, dyn));}}

程式碼部分除了應用正弦波外也使用了音雲的概念,條件設定是概念與第三

段落是採相同方式構成,不同點在於,本範例是以同一正弦波方程式為基礎,應

用了亂數類別改變 sin 括號中的分母值,此外,也在節奏和力度上做亂數;現場演

奏部分則是採即興方式搭配整個段落音響氛圍,整個段落的音高結構如下圖(圖

Page 86: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

80

4-3-d)。

【圖 4-3-d】作品《幻實之鏡》第四段落《幻》音高構成分布圖

最後的段落為《理性》,這個段落將使用由作曲家荀白克(Arnold Schoenberg,

1874-1951, 後文以荀白克簡稱之)所提出的音樂理論「十二音列」做為基礎,並融

合前面文章中使用的亂數類別,成為落實音樂理論與電腦科技結合的段落,表現

方式上以類似第三段落的方式,將現場演奏部分融入三聲部其中一個聲部,聲部

選擇上亦相同。

音列的選擇,是使用荀白克著名的《第二十五號鋼琴組曲》(Suite for Clavier,

op.25, 1923)的前奏曲中使用之音列為素材,此音列音高如下方譜例表示(譜例

4-3-iii)。

【譜例 4-3-iii】荀白克《第二十五號鋼琴組曲》前奏曲中基本音列

Page 87: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

81

首要步驟是將此音列關係如實呈現的轉換成程式碼,使用的方法為程式碼編

寫中陣列,並且為了因應使用時高低八度轉換之可能性,因此在每一個音前方都

多設定一個對應的變數,最終變數條件設定及基本音列如下方範例中所呈現(範例

二十八):

【範例二十八】第五段落《理性》譜例 4-3-iii 音列程式碼化

1. int j = 5+randomNumber.nextInt(3);

2. int x = 12 * j;

3. int y = 12 * (j-1);

4. int z = 12 * (j-2);

5. int []pitcharray0=

{(x+4),(x+5),(y+7),(x+1),(y+6),(y+3),(y+8),(y+2),(y+11),(z+0),(z+9),(z+10)};

接著,按一般分析音列作品或使用音列創作時常用的方式,將此音列的矩陣

先列出,如同下方範例呈現(範例二十九):

【範例二十九】範例二十八之音列程式碼矩陣化

1. int []pitcharray0=

{(x+4),(x+5),(y+7),(x+1),(y+6),(y+3),(y+8),(y+2),(y+11),(z+0),(z+9),(z+10)};

2. int []pitcharray1=

{(x+5),(x+6),(y+8),(x+2),(y+7),(y+4),(y+9),(y+3),(y+0),(z+1),(z+10),(z+11)};

3 .int []pitcharray2=

{(x+6),(x+7),(y+9),(x+3),(y+8),(y+5),(y+10),(y+4),(y+1),(z+2),(z+11),(z+0)};

4. int []pitcharray3=

{(x+7),(x+8),(y+10),(x+4),(y+9),(y+6),(y+11),(y+5),(y+2),(z+3),(z+0),(z+1)};

5. int []pitcharray4=

{(x+8),(x+9),(y+11),(x+5),(y+10),(y+7),(y+0),(y+6),(y+3),(z+4),(z+1),(z+2)};

6. int []pitcharray5=

{(x+9),(x+10),(y+0),(x+6),(y+11),(y+8),(y+1),(y+7),(y+4),(z+5),(z+2),(z+3)};

7. int []pitcharray6=

{(x+10),(x+11),(y+1),(x+7),(y+0),(y+9),(y+2),(y+8),(y+5),(z+6),(z+3),(z+4)};

8. int []pitcharray7=

{(x+11),(x+0),(y+2),(x+8),(y+1),(y+10),(y+3),(y+9),(y+6),(z+7),(z+4),(z+5)};

9. int []pitcharray8=

{(x+0),(x+1),(y+3),(x+9),(y+2),(y+11),(y+4),(y+10),(y+7),(z+8),(z+5),(z+6)};

10. int []pitcharray9=

{(x+1),(x+2),(y+4),(x+10),(y+3),(y+0),(y+5),(y+11),(y+8),(z+9),(z+6),(z+7)};

11. int []pitcharray10=

{(x+2),(x+3),(y+5),(x+11),(y+4),(y+1),(y+6),(y+0),(y+9),(z+10),(z+7),(z+8)};

Page 88: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

82

12. int []pitcharray11=

{(x+3),(x+4),(y+6),(x+0),(y+5),(y+2),(y+7),(y+1),(y+10),(z+11),(z+8),(z+9)};

在列出所有音列後,為了讓電腦在執行時可以選擇要使用哪一組音列和不同

的節奏,因此對於樂句帶入音高和節奏的選擇上,使用亂數類別、if 選擇敘述式和

if…else 選擇敘述式串聯設立選擇條件,成為下方範例中的結果(範例三十):

【範例三十】第五段落《理性》節奏陣列亂數選擇與音高亂數設置條件選擇

1. double []rhythmarray ={4,2,1.75,1.5,1.25,1,0.75,0.5,0.25,0.333,0.2,0.125};

2. double i = rhythmarray[ randomNumber.nextInt(11)];

3. int l = randomNumber.nextInt(100);

4. if(l%2==0){

5. phr.addNoteList(pitcharray0,i);}

6. else if(l%3==0){

7. phr.addNoteList(pitcharray1,i);}

8. else if(l%4==0){

9. phr.addNoteList(pitcharray2,i);}

10. else if(1%5==0){

11. phr.addNoteList(pitcharray3,i);}

12. else if(l%6==0){

13. phr.addNoteList(pitcharray4,i);}

14. else if(l%7==0){

15. phr.addNoteList(pitcharray5,i);}

16. else if(l%8==0){

17. phr.addNoteList(pitcharray6,i);}

18. else if(l%9==0){

19. phr.addNoteList(pitcharray7,i);}

20. else if(l%10==0){

21. phr.addNoteList(pitcharray8,i);}

22. else if(l%11==0){

23. phr.addNoteList(pitcharray9,i);}

24. else if(l%12==0){

25. phr.addNoteList(pitcharray10,i);}

26. else{

27. phr.addNoteList(pitcharray11,i);}

最後是創作手法的選擇與使用,在此使用的是“jm.music.tools.*”中的“Mod”類

別,許多創作常用的手法和效果,如漸強(crescendo)、漸弱(diminuendo)、淡入(fade

in)、淡出(fade out)或是反覆(repeat)等等指令都編列在此,而選擇敘述式的編成方

法也同範例三十,編寫方式如同下方範例(範例三十一):

【範例三十一】第五段落《理性》創作手法相關選擇敘述式串聯

Page 89: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

83

1. if (l % 2 == 0){

2. Mod.palindrome(phr);}

3. else if (l % 3 == 0){

4. Mod.rotate(phr);}

5. else if(l%4==0){

6. Mod.inversion(phr);}

7. else if(l%5==0){

8. Mod.shake(phr);}

9. else{

10. Mod.retrograde(phr);}

上述四個範例(從範例二十八至三十一)都隸屬於在條件為 “(int a=0; a<15;

a++)”的 for 迴圈敘述式中的一部分,不僅共用相同的迴圈執行次數,也共用相同

的變數條件,整個段落則由三個相同結構的程式碼組成,使最終現場演奏時的樂

譜也能在同樣的編寫基礎下產生。音高結構的分布,由於會隨著亂數而使得每次

執行都會有不同的結果,因此,以下音高分布圖(圖 4-3-e)僅為其中一例作為參考。

【圖 4-3-e】第五段落《理性》音高分布圖

Page 90: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

84

Page 91: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

85

第五章 結論

綜合了從基礎的各式敘述式和運算子、jMusic 下將音樂風格套用的實例到實

際去運用 jMusic 來創作作品,在使用 Java 語言這種需要複數領域的相關知識創作

過程中最大也最困難的,如同在第一章的序中也曾提及的,對於筆者而言,同時

也對於未來欲投身以 jMusic 來創作的作曲者而言,有以下幾個部分:

第一個面臨的問題,也是最基本的,便是操作。使用 Eclipse 編寫程式碼的過

程相較於使用別人已經編寫完整、除錯且一再檢視的程式有很大的不同。程式碼

本身是構成程式的基礎,可以想像程式本身是一台設計精密的機械或鐘錶,而程

式碼只是這台機械裡的一個小齒輪、螺絲或是部件,每一個環節只要出了點錯,

有時錯誤是明顯可見的,有時問題小到存在於盲點之中,兩種錯誤相較下,前者

雖然不一定會是容易處理的情況,但只要能發現就能以各種可能的方式去處理;

後者錯誤雖小,但卻往往消耗了程式設計者許多時間去反覆閱讀、反覆檢查,但

不論是哪種型式的錯誤,對於電腦這個執行媒介而言,本身就無法執行,不像人

類大腦那樣的靈活變通,可以容許有各式各樣的例外產生。

第二個將會面臨到的問題,從基本數學邏輯與概念,到更進一步的,是關於

數學方程的知識。這些部分不僅反應在 jMusic 的使用上,甚至在使用 jMusic 創作

之前。單就在 Eclipse 使用上,程式語言編寫基礎所需要面對的就是各式各樣的數

學邏輯,而認識各種敘述式在學習過程中實為是容易的部分,因為只要記下它的

Page 92: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

86

架構和功能,在使用單純條件的前提下都可以簡單的帶入;逐漸困難的是當程式

碼的構成越來越複雜的情況,越是複雜的程式碼,有時也包含了相對複雜的邏輯

概念在它的條件中,或者需要提供相應的附帶條件去控制,定下那些條件的前提

就是必須要理解所有程式的運作,各種續數是會產生的結果,進而以數學邏輯的

思考去控制。

反觀到使用 jMusic 的情況,同樣是數學領域的問題,這點對於大部分單純只

有音樂背景的人相對而言是創作上最大的障礙,筆者本身也不例外,但這樣的障

礙其實該歸究於環境本身?還是個人因素造成?以大部分情況判斷前者才是主要

因素,或者又能說兩個原因本身也互為因果關係。在國內大部分學習音樂的學生

在學習的歷程中,由於各個階段考試的重點科目和高中階段分類組的影響,許多

人逐漸忽視數學,甚至是放棄了數學,因此對於在數學領域上的知識只有達到高

中水準甚至以下水準的狀態下(相當於是在基礎幾何方程式的程度),在創作構圖的

過程能使用的素材多樣性就相對大大的減少,換言之,假如以此為創作媒介情況

下,當作曲者越是希望做到複雜且完整的創作,就越需要數學領域的知識支撐。

第三個會面臨的問題是存在於電腦音樂和以往的在樂譜上的創作兩者間的差

異性。這兩者最大的差異在於創作上的習慣,即便兩者都同樣是將抽像的音樂化

為特定符號的方式呈現,但對於大多數學音樂的人在學習歷程上,學習各式理論

不管是基礎樂理、和聲、樂曲分析等等,所接觸的都是記錄在能見的樂譜上,也

間接養成依賴樂譜的習慣。而以 Java 語言創作時的情況大為不同的是,不像將音

符寫在五線譜上時音高和許多創作時需要和想要去讀到和看到的關係是明確的,

像是橫向線條及和聲進行的發展、縱向的和聲結構以及多個聲部間的對位關係等

等;Java 語言下的創作中,作曲者能閱讀到的僅僅是文字、是指令、是各種邏輯

Page 93: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

87

推演的概念,縱使 jMusic 的 API 中已有系統的將各種類別指令做整合,也能藉由

特定指令使之顯示音高分部和聲部結構,但在把實際音符轉為文字指令或是以方

程式的過程,或是段落間的連結,都需要把原先記譜的想法加以轉換,若非是在

有特別需要的情況下,這些部份的構築和串聯反而更加耗時。

綜觀上述幾個要點,坦白而言,雖然是困難但也並非是缺點,只是由於此類

型的創作應將其視為是需要同時兼具數學、資訊工程、音樂以及音樂相關之音學、

音響學等等多重學術領域背景,方能再使用上、建構上、創作甚至是創新上游刃

有餘。對於國內目前類組專業劃界分明的學習、教育指導方針下,能達成這項前

提者相對屬少數,若是培養相關專才,亦需要特別重點課程規劃,以音樂背景的

學生而言,所需的便是數學知識的補強、其他領域者相對也需要相當音樂知識;

若在非就學期間自行研究,除了需要耗費相當多時間外,也可能因未經過有系統

學習和訓練而產生認知上的錯誤;因此就未來可能發展的方向而言,筆者認為此

類型創作最初階段能藉由跨領域合作的方式來達成,當此階段成熟後,才有可能

進一步各自獨立以各別擅長領域去著手創作出不同的音樂風格。

最後,回歸到初衷,對於現環境而言,不管是音樂創作上、音樂展演及表現

方式上,要如何寫的創新?如何演的特別?或是更根本的,應該維持現況還是尋

求改變?改變的方式有什麼?這些都是須投身嘗試後才可能找尋到新的道路及方

向。在本篇論文中,筆者僅以自身各領域有限的知識背景去實驗尋求新的創作之

道,求新求變過程必定會面臨各式各樣的挑戰,並非平順、筆直且容易的,但求

知的過程本是如此,也望藉此使得電腦相關的新興領域能獲得更多的關注,使得

電腦音樂素材的運用能引起更多的研究和討論。

Page 94: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

參考文獻

【翻譯專書】

Deitel, P.J., Deitel, H.M..《程式設計藝術》(Java: How to Program)。陸茵、楊安渡、

傅日明 譯。臺北:金華,2010。

宮本信二。《Eclipse 完全攻略:從基礎 Java 到 PDE 外掛開發》。廖文賦、博碩文化

譯。臺北:博碩文化,2011。

【學術論文】

黃靜芳。《電腦輔助國小四年級音樂欣賞教學之研究-以程式 MAX/MSP 之應用為

例》。國立臺北教育大學研究所碩士論文,2000。

許擎亞。《自動化長笛與準則化音樂控制之研究》。國立交通大學研究所碩士論文,

2008。

黃玉生。《電腦科技在音樂創作上之應用》。國立台北教育大學,2003。

【外文書目】

Morgan, Robert P.. Twentieth-Century Music: A History of Musical Style in Modern

Europe and America. New York: Norton, 1991.

Schwarz, K. Robert. Minimalists. London: Phaidon, 1996.

Taube, Heinrich K.. Notes from the Metalevel:Introduction to Algorithmic Music

Composition. London: Taylor & Francis Group plc, 2004.

Page 95: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

附錄

附件一、《幻實之鏡》第一段落《序》完整程式碼:(節尾段落再次使用)

1. package ThesisComposition1;

2. import java.util.Random;

3. import jm.JMC;

4. import jm.music.data.*;

5. import jm.util.*;

6. import java.lang.Math;

7. import jm.music.tools.*;

8. public class TC implements JMC {

9.

10. public static void main(String[] args) {

11. Score s = new Score("TC");

12. s.setTimeSignature(4,4);

13. s.setTempo(50.0);

14. Part p1= new Part("Wind Effect", WIND,0);

15. Part p2= new Part("TS",44,1);

16. Part p3= new Part("TS2",44,2);

17. Part p4= new Part("Slap",SLAP,3);

18. Phrase phr1 = new Phrase();

19. Phrase phr2 = new Phrase();

20. Phrase phr3 = new Phrase();

21. Phrase phr4 = new Phrase();

22. phr2.setStartTime(20.0);

23. phr3.setStartTime(28.0);

24. phr4.setStartTime(28.0);

25.

26. int [] pitcharray = {0, 35, 0, 35, 0,35};

27. double [] rhythmarray = {0.0, DHN, 0.0, DHN,0.0, 7.0};

28. phr1.addNoteList(pitcharray, rhythmarray);

29. Mod.repeat(phr1,2);

30. Note n = new Note(35,12);

31. phr1.addNote(n);

32. Mod.decrescendo(phr1, 23.0,50.0,60,40);

33. for(int i=0; i<127; i++){

34. int pitch= i;

35. Note n1= new Note(pitch, 0.0625,60);

Page 96: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

36. Mod.crescendo(phr2, 20.0, 35.0, 60, 80);

37. phr2.addNote(n1);

38. Note n2 = new Note (127, 0.0625,60);

39. phr3.addNote(n2);

40. Mod.decrescendo(phr3, 35.0, 55.0,60,30);}

41.

42. double cloudDensity1 = 0.01;

43. Random randomNumber= new Random();

44. for(int j = 0; j < 2000; j++) {

45. int pitch1 = 60+randomNumber.nextInt(67);

46. double rv = Math.random() * cloudDensity1;

47. int rDyn = (int)(Math.random()*127);

48. phr4.addNote(new Note(pitch1, rv, rDyn));}

49.

50. int u =20;

51. int n1 = 100;

52. double density = 0.001;

53.

54. for(int k=500; k>0; k--){

55. if(k%5==0)n1--;

56. if(k%25==0)u--;

57. int pitch2= (int)Math.abs((Math.sin(k / density) * u + n1));

58. Note n3= new Note(pitch2, 0.01,60);

59. Mod.crescendo(phr2, 55.0, 60.0, 60, 10);

60. phr4.addNote(n3);}

61.

62. p1.addPhrase(phr1);

63. p2.addPhrase(phr2);

64. p3.addPhrase(phr3);

65. p4.addPhrase(phr4);

66. s.addPart(p1);

67. s.addPart(p2);

68. s.addPart(p3);

69. s.addPart(p4);

70. Write.midi(s, "TC.mid");

71. View.show(s);

72. Play.midi(s);}}

Page 97: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

附件二、《幻實之鏡》第二段落《詭譎》完整程式碼:

1. package ThesisComposition1;

2. import jm.JMC;

3. import jm.music.data.*;

4. import jm.util.*;

5. import java.lang.Math;

6. import jm.music.tools.*;

7. public class TC2 implements JMC{

8.

9. public static void main(String[] args){

10. Score s = new Score("TC2");

11. s.setTimeSignature(1,4);

12. s.setTempo(200.0);

13. Part p = new Part("WIND Effect", WIND, 0);

14. Part p1 = new Part ("Steeldrum", CLARINET,1);

15. Part p2 = new Part ("Bird", BIRD,2);

16. Phrase phr = new Phrase();

17. Phrase phr1 = new Phrase();

18. Phrase phr2 = new Phrase();

19. phr2.setStartTime(20);

20. double density = 2.0;

21. int u = 0;

22. int n = 30;

23. int q = 100;

24. int m = 0;

25.

26. for(int i = 10; i < 5000;i++){

27. if(i % 200 == 0) u++;

28. if(i % 100 == 0) n++;

29. int pitch = (int)Math.abs((Math.sin(i / density) * u + n));

30. if(pitch >127) pitch=127;

31. Note note = new Note(pitch, DSQ,20);

32. phr.addNote(note);

33. Mod.crescendo(phr, 60, 490, 20, 70);}

34.

35. for(int j=0; j< 5000; j++){

36. if(j % 100 == 0) q--;

37. if(j % 200 == 0) m++;

Page 98: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

38. int pitch1 = (int) Math.abs((Math.sin(j / density) *m + q));

39. Note note1 = new Note (pitch1,DSQ,10);

40. if (pitch1>127)pitch1=127;

41. phr1.addNote(note1);

42. Mod.crescendo(phr1, 60, 520, 10, 70);}

43.

44. double density2=10.0;

45. int j = 10;

46.

47. for(int i = 0; i < 1600; i++) {

48. int pitch2 = (int) Math.abs((Math.sin(i/density2) * j + 60 ));

49. if (i%50==0) j++;

50. if (pitch2 >127) pitch2=127;

51. if (pitch2 < 0 ) pitch2=0;

52. if(pitch2 <55) pitch2++;

53. if(pitch2 >=90) pitch2=120;

54. if(pitch2<=40) pitch2=30;

55. Note note2 = new Note(pitch2, DSN,10);

56. phr2.addNote(note2);

57. Mod.crescendo(phr2, 45, 530, 10, 90);}

58.

59. for(int i=4999; i>10; i--){

60. if(i % 200 == 0) u--;

61. if(i % 100 == 0) n--;

62. int pitch = (int)Math.abs((Math.sin(i / density) * u + n));

63. if(pitch <0) pitch=0;

64. Note note = new Note(pitch, DSQ,70);

65. phr.addNote(note);

66. phr.setTempo(1000*(density*i+1)/(density*i));

67. Mod.decrescendo(phr, 500, 1500, 70, 2);}

68.

69. for(int j1=4999; j1>10; j1--){

70. if(j1 % 100 == 0) q++;

71. if(j1 % 200 == 0) m--;

72. int pitch1 = (int) Math.abs((Math.sin(j1 / density) *m + q));

73. Note note1 = new Note (pitch1,DSQ,70);

74. if (pitch1>127)pitch1=127;

75. phr1.addNote(note1);

76. phr1.setTempo(1000*(density*j1+1)/(density*j1));

Page 99: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

77. Mod.decrescendo(phr1, 500, 1500, 70, 20);}

78.

79. int j2=42;

80.

81. for(int i=1599; i>0;i--){

82. int pitch2 = (int) Math.abs((Math.sin(i/density2) * j2 + 60 ));

83. if (i%50==0) j2--;

84. if (pitch2 >127) pitch2=127;

85. if (pitch2 < 0 ) pitch2=0;

86. if(pitch2 >=90) pitch2=120;

87. if(pitch2<=40) pitch2=30;

88. Note note2 = new Note(pitch2, DSN,70);

89. phr2.addNote(note2);

90. phr2.setTempo(1000*(density*i+1)/(density*i));

91. Mod.decrescendo(phr2, 531, 1500,70,20);}

92.

93. p.addPhrase(phr);

94. p1.addPhrase(phr1);

95. p2.addPhrase(phr2);

96. s.addPart(p);

97. s.addPart(p1);

98. s.addPart(p2);

99. Write.midi(s, "TC2.mid");

100. View.show(s);

101. Play.midi(s);}}

Page 100: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

附件三、《幻實之鏡》第三段落《違和》完整程式碼:

1. package ThesisComposition1;

2. import jm.JMC;

3. import jm.music.data.*;

4. import jm.util.*;

5. import java.lang.Math;

6. public class TC3 implements JMC{

7.

8. public static void main(String[] args) {

9. Score s = new Score("TC3");

10. s.setTempo(100);

11. Part p1 = new Part("Violin",VIOLIN,1);

12. Part p2 = new Part ("ViolinII", VIOLIN,2);

13. Part p3 = new Part ("Viola", VIOLA,3);

14. Phrase phr = new Phrase();

15. Phrase phr1 = new Phrase();

16. Phrase phr2 = new Phrase();

17.

18. for (int i = 10; i < 400; i++) {

19. double density= 1.0;

20. int pitch = 0;

21. if (i % 2 == 0) {

22. pitch = (int) (Math.sin(i/density ) * -5 + 80);

23. } else if (i % 3 == 0) {

24. pitch = (int) (Math.sin(i/density ) * 10 + 80);

25. }else if(i%4==0){

26. pitch = (int) (Math.sin(i/density ) * 15 + 80);

27. }else{

28. pitch = (int) (Math.sin(i/density ) * -20 + 80);

29. }

30. if (pitch < 55)

31. pitch = 55;

32. if (pitch > 85)

33. pitch = 85;

34. Note n = new Note(pitch, 0.25);

35. phr.addNote(n);}

36.

37. /*for (int i = 10; i < 680; i++) {

Page 101: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

38. double density= 1.0;

39. int pitch2 = 0;

40. if (i % 2 == 0) {

41. pitch2 = (int) (Math.sin(i / density) * 5 + 80);

42. } else if (i % 3 == 0) {

43. pitch2 = (int) (Math.sin(i / density) * -10 + 80);

44. }else if(i%4==0){

45. pitch2 = (int) (Math.sin(i / density) * -15 + 80);

46. }else{

47. pitch2= (int) (Math.sin(i / density) * 20 + 80);

48. }

49. if (pitch2 < 55)

50. pitch2 = 55;

51. if (pitch2 > 85)

52. pitch2 = 85;

53. Note n2 = new Note(pitch2, 0.25);

54. phr1.addNote(n2);}*/

55.

56. for (int i=10; i<180; i++){

57. phr1.addNote(48,1);}

58.

59. for (int i = 10; i < 400; i++) {

60. double density= 1.0;

61. int pitch3 = 0;

62. if (i % 2 == 0) {

63. pitch3 = (int) (Math.sin(i / density) * 5 + 70);

64. } else if (i % 3 == 0) {

65. pitch3 = (int) (Math.sin(i / density) * -10 + 70);

66. }else if(i%4==0){

67. pitch3 = (int) (Math.sin(i / density) * -15 + 70);

68. }else{

69. pitch3= (int) (Math.sin(i / density) * 20 + 70);

70. }

71. if (pitch3 < 48)

72. pitch3 = 48;

73. if (pitch3 > 74)

74. pitch3 = 74;

75. Note n3 = new Note(pitch3, 0.333);

76. phr2.addNote(n3);

Page 102: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

77. phr2.setTempo(120*i/i-1);}

78.

79. for (int i = 10; i < 300; i++) {

80. double density= 1.0;

81. int pitch1 = 0;

82. if (i % 2 == 0) {

83. pitch1 = (int) (Math.sin(i/density ) * -5 + 80);

84. } else if (i % 3 == 0) {

85. pitch1 = (int) (Math.sin(i/density ) * 10 + 80);

86. }else if(i%4==0){

87. pitch1 = (int) (Math.sin(i/density ) * 15 + 80);

88. }else{

89. pitch1 = (int) (Math.sin(i/density ) * -20 + 80);

90. }

91. if (pitch1 < 55)

92. pitch1 = 55;

93. if (pitch1 > 85)

94. pitch1 = 85;

95. Note n1 = new Note(pitch1, 0.25);

96. phr.addNote(n1);}

97.

98. phr1.setStartTime(8);

99. phr2.setStartTime(40);

100. p1.addPhrase(phr);

101. p2.addPhrase(phr1);

102. p3.addPhrase(phr2);

103. s.addPart(p1);

104. s.addPart(p2);

105. s.addPart(p3);

106. Write.midi(s,"TC3.mid");

107. View.show(s);

108. Play.midi(s);}}

Page 103: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

附件四、《幻實之鏡》第四段落《幻》完整程式碼:

1. import java.util.Random;

2. import jm.JMC;

3. import jm.music.data.*;

4. import jm.util.*;

5. import java.lang.Math;

6. public class TC4 implements JMC{

7.

8. public static void main(String[] args) {

9. Score s = new Score("TC4");

10. Part p1 = new Part("Bird",BIRD,1);

11. Part p2 = new Part ("Wind", WIND,2);

12. Part p3 = new Part ("ICERAIN", ICERAIN,3);

13. Phrase phr = new Phrase();

14. Phrase phr1 = new Phrase();

15. Phrase phr2 = new Phrase();

16. Random randomNumber= new Random();

17.

18. for(int i=0; i<300;i++){

19. int a = 0;

20. if (i % 2 == 0){

21. a = 90;

22. }else if(i % 3 == 0){

23. a = 30;

24. }else if(i % 4 == 0){

25. a = 127;

26. }else{

27. a = 60;

28. int pitch = (int)(Math.sin(i/1+randomNumber.nextInt(a-1)) * 10 +60);

29. if (pitch <0) pitch=0;

30.

31. double rhythm = 0.0;

32. rhythm = (randomNumber.nextDouble())*(randomNumber.nextInt(100));

33. if (rhythm > 2.0)rhythm = 2.0;

34. if (rhythm < 0.0)rhythm=0.0;

35. int dyn = (int)(Math.random()*127);

36. phr.addNote(new Note(pitch, rhythm, dyn));}}

37.

Page 104: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

38. for(int i=0; i<300;i++){

39. int a = 0;

40. if (i % 2 == 0){

41. a = 90;

42. }else if(i % 3 == 0){

43. a = 30;

44. }else if(i % 4 == 0){

45. a = 127;

46. }else{

47. a = 60;

48. int pitch = (int)(Math.sin(i/1+randomNumber.nextInt(a-1)) * 10 +60);

49. if (pitch <0) pitch=0;

50. double rhythm = 0.0;

51. rhythm = (randomNumber.nextDouble())*(randomNumber.nextInt(100));

52. if (rhythm > 4.0)rhythm = 4.0;

53. if (rhythm < 0.0)rhythm=0.0;

54. int dyn = (int)(Math.random()*127);

55. phr1.addNote(new Note(pitch, rhythm, dyn));}}

56.

57. for(int i=0; i<300;i++){

58. int a = 0;

59. if (i % 2 == 0){

60. a = 90;

61. }else if(i % 3 == 0){

62. a = 30;

63. }else if(i % 4 == 0){

64. a = 127;

65. }else{

66. a = 60;

67. int pitch = (int)(Math.sin(i/1+randomNumber.nextInt(a-1)) * 10 +60);

68. if (pitch <0) pitch=0;

69.

70. double rhythm = 0.0;

71. rhythm = (randomNumber.nextDouble())*(randomNumber.nextInt(100));

72. if (rhythm > 2.0)rhythm = 2.0;

73. if (rhythm < 0.0)rhythm=0.0;

74. int dyn = (int)(Math.random()*127);

75. phr2.addNote(new Note(pitch, rhythm, dyn));}}

76.

Page 105: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

77. p1.addPhrase(phr);

78. p2.addPhrase(phr1);

79. p3.addPhrase(phr2);

80. s.addPart(p1);

81. s.addPart(p2);

82. s.addPart(p3);

83. Write.midi(s,"TC4.mid");

84. View.show(s);

85. Play.midi(s);}}

Page 106: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

附件五、《幻實之鏡》第五段落《理性》完整程式碼:

1. package ThesisComposition1;

2. import java.util.Random;

3. import jm.JMC;

4. import jm.music.data.*;

5. import jm.util.*;

6. import jm.music.tools.*;

7. public class TC5 implements JMC{

8.

9. @SuppressWarnings("unused")

10. public static void main(String[] args) {

11. Score s = new Score("TC5", 90.0);

12. s.setTimeSignature(4,4);

13. Part p1 = new Part("Violn",PIANO,1);

14. Part p2 = new Part ("ViolnII", VIOLIN,2);

15. Part p3 = new Part ("Viola", VIOLA,3);

16. Phrase phr = new Phrase();

17. Phrase phr1 = new Phrase();

18. Phrase phr2 = new Phrase();

19. Random randomNumber= new Random();

20.

21. for(int a=0; a<5; a++){

22. int j = 5+randomNumber.nextInt(3);

23. int x = 12*j;

24. int y = 12*(j-1);

25. int z = 12*(j-2);

26. int []pitcharray0=

{(x+4),(x+5),(y+7),(x+1),(y+6),(y+3),(y+8),(y+2),(y+11),(z+0),(z+9),(z+10)};

27. int []pitcharray1=

{(x+5),(x+6),(y+8),(x+2),(y+7),(y+4),(y+9),(y+3),(y+0),(z+1),(z+10),(z+11)};

28. int []pitcharray2=

{(x+6),(x+7),(y+9),(x+3),(y+8),(y+5),(y+10),(y+4),(y+1),(z+2),(z+11),(z+0)};

29. int []pitcharray3=

{(x+7),(x+8),(y+10),(x+4),(y+9),(y+6),(y+11),(y+5),(y+2),(z+3),(z+0),(z+1)};

30. int []pitcharray4=

{(x+8),(x+9),(y+11),(x+5),(y+10),(y+7),(y+0),(y+6),(y+3),(z+4),(z+1),(z+2)};

31. int []pitcharray5=

{(x+9),(x+10),(y+0),(x+6),(y+11),(y+8),(y+1),(y+7),(y+4),(z+5),(z+2),(z+3)};

Page 107: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

32. int []pitcharray6=

{(x+10),(x+11),(y+1),(x+7),(y+0),(y+9),(y+2),(y+8),(y+5),(z+6),(z+3),(z+4)};

33. int []pitcharray7=

{(x+11),(x+0),(y+2),(x+8),(y+1),(y+10),(y+3),(y+9),(y+6),(z+7),(z+4),(z+5)};

34. int []pitcharray8=

{(x+0),(x+1),(y+3),(x+9),(y+2),(y+11),(y+4),(y+10),(y+7),(z+8),(z+5),(z+6)};

35. int []pitcharray9=

{(x+1),(x+2),(y+4),(x+10),(y+3),(y+0),(y+5),(y+11),(y+8),(z+9),(z+6),(z+7)};

36. int []pitcharray10=

{(x+2),(x+3),(y+5),(x+11),(y+4),(y+1),(y+6),(y+0),(y+9),(z+10),(z+7),(z+8)};

37. int []pitcharray11=

{(x+3),(x+4),(y+6),(x+0),(y+5),(y+2),(y+7),(y+1),(y+10),(z+11),(z+8),(z+9)};

38. double []rhythmarray ={4,2,1.75,1.5,1.25,1,0.75,0.5,0.25,0.333,0.2,0.125};

39. double i = rhythmarray[ randomNumber.nextInt(11)];

40. int l = randomNumber.nextInt(1000);

41. if(l%2==0){

42. phr.addNoteList(pitcharray0,i);}

43. else if(l%3==0){

44. phr.addNoteList(pitcharray1,i);}

45. else if(l%5==0){

46. phr.addNoteList(pitcharray2,i);}

47. else if(1%7==0){

48. phr.addNoteList(pitcharray3,i);}

49. else if(l%11==0){

50. phr.addNoteList(pitcharray4,i);}

51. else if(l%13==0){

52. phr.addNoteList(pitcharray5,i);}

53. else if(l%17==0){

54. phr.addNoteList(pitcharray6,i);}

55. else if(l%19==0){

56. phr.addNoteList(pitcharray7,i);}

57. else if(l%23==0){

58. phr.addNoteList(pitcharray8,i);}

59. else if(l%29==0){

60. phr.addNoteList(pitcharray9,i);}

61. else if(l%31==0){

62. phr.addNoteList(pitcharray10,i);}

63. else{

64. phr.addNoteList(pitcharray11,i);}

Page 108: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

65. int m = randomNumber.nextInt(50);

66. if (m % 2 == 0){

67. Mod.palindrome(phr);}

68. else if (m % 3 == 0){

69. Mod.rotate(phr);}

70. else if(m % 4 ==0){

71. Mod.inversion(phr);}

72. else if(m % 5 ==0){

73. Mod.shake(phr);}

74. else{

75. Mod.retrograde(phr);}}

76.

77. /*for(int a=0; a<5; a++){

78. int j = 6+randomNumber.nextInt(3);

79. int x = 12*j;

80. int y = 12*(j-1);

81. int z = 12*(j-2);

82. int []pitcharray0=

{(x+4),(x+5),(y+7),(x+1),(y+6),(y+3),(y+8),(y+2),(y+11),(z+0),(z+9),(z+10)};

83. int []pitcharray1=

{(x+5),(x+6),(y+8),(x+2),(y+7),(y+4),(y+9),(y+3),(y+0),(z+1),(z+10),(z+11)};

84. int []pitcharray2=

{(x+6),(x+7),(y+9),(x+3),(y+8),(y+5),(y+10),(y+4),(y+1),(z+2),(z+11),(z+0)};

85. int []pitcharray3=

{(x+7),(x+8),(y+10),(x+4),(y+9),(y+6),(y+11),(y+5),(y+2),(z+3),(z+0),(z+1)};

86. int []pitcharray4=

{(x+8),(x+9),(y+11),(x+5),(y+10),(y+7),(y+0),(y+6),(y+3),(z+4),(z+1),(z+2)};

87. int []pitcharray5=

{(x+9),(x+10),(y+0),(x+6),(y+11),(y+8),(y+1),(y+7),(y+4),(z+5),(z+2),(z+3)};

88. int []pitcharray6=

{(x+10),(x+11),(y+1),(x+7),(y+0),(y+9),(y+2),(y+8),(y+5),(z+6),(z+3),(z+4)};

89. int []pitcharray7=

{(x+11),(x+0),(y+2),(x+8),(y+1),(y+10),(y+3),(y+9),(y+6),(z+7),(z+4),(z+5)};

90. int []pitcharray8=

{(x+0),(x+1),(y+3),(x+9),(y+2),(y+11),(y+4),(y+10),(y+7),(z+8),(z+5),(z+6)};

91. int []pitcharray9=

{(x+1),(x+2),(y+4),(x+10),(y+3),(y+0),(y+5),(y+11),(y+8),(z+9),(z+6),(z+7)};

92. int []pitcharray10=

{(x+2),(x+3),(y+5),(x+11),(y+4),(y+1),(y+6),(y+0),(y+9),(z+10),(z+7),(z+8)};

Page 109: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

93. int []pitcharray11=

{(x+3),(x+4),(y+6),(x+0),(y+5),(y+2),(y+7),(y+1),(y+10),(z+11),(z+8),(z+9)};

94. double []rhythmarray

={4,2,1.75,1.5,1.25,1,0.75,0.5,0.25,0.333,0.2,0.125};

95. double i = rhythmarray[ randomNumber.nextInt(11)];

96. int l = randomNumber.nextInt(100);

97. if(l%2==0){

98. phr1.addNoteList(pitcharray0,i);}

99. else if(l%3==0){

100. phr1.addNoteList(pitcharray1,i);}

101. else if(l%5==0){

102. phr1.addNoteList(pitcharray2,i);}

103. else if(1%7==0){

104. phr1.addNoteList(pitcharray3,i);}

105. else if(l%6==0){

106. phr1.addNoteList(pitcharray4,i);}

107. else if(l%7==0){

108. phr1.addNoteList(pitcharray5,i);}

109. else if(l%8==0){

110. phr1.addNoteList(pitcharray6,i);}

111. else if(l%9==0){

112. phr1.addNoteList(pitcharray7,i);}

113. else if(l%10==0){

114. phr1.addNoteList(pitcharray8,i);}

115. else if(l%11==0){

116. phr1.addNoteList(pitcharray9,i);}

117. else if(l%12==0){

118. phr1.addNoteList(pitcharray10,i);}

119. else{

120. phr1.addNoteList(pitcharray11,i);}

121. int m = randomNumber.nextInt(50);

122. if (m % 2 == 0){

123. Mod.palindrome(phr1);}

124. else if (m % 3 == 0){

125. Mod.rotate(phr1);}

126. else if(m % 4 ==0){

127. Mod.inversion(phr1);}

128. else if(m % 5 ==0){

129. Mod.shake(phr1);}

Page 110: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

130. else{

131. Mod.retrograde(phr1);}}*/

132.

133. for(int a=0; a<5; a++){

134. int j = 4+randomNumber.nextInt(4);

135. int x = 12*j;

136. int y = 12*(j-1);

137. int z = 12*(j-2);

138. int []pitcharray0=

{(x+4),(x+5),(y+7),(x+1),(y+6),(y+3),(y+8),(y+2),(y+11),(z+0),(z+9),(z+10)};

139. int []pitcharray1=

{(x+5),(x+6),(y+8),(x+2),(y+7),(y+4),(y+9),(y+3),(y+0),(z+1),(z+10),(z+11)};

140. int []pitcharray2=

{(x+6),(x+7),(y+9),(x+3),(y+8),(y+5),(y+10),(y+4),(y+1),(z+2),(z+11),(z+0)};

141. int []pitcharray3=

{(x+7),(x+8),(y+10),(x+4),(y+9),(y+6),(y+11),(y+5),(y+2),(z+3),(z+0),(z+1)};

142. int []pitcharray4=

{(x+8),(x+9),(y+11),(x+5),(y+10),(y+7),(y+0),(y+6),(y+3),(z+4),(z+1),(z+2)};

143. int []pitcharray5=

{(x+9),(x+10),(y+0),(x+6),(y+11),(y+8),(y+1),(y+7),(y+4),(z+5),(z+2),(z+3)};

144. int []pitcharray6=

{(x+10),(x+11),(y+1),(x+7),(y+0),(y+9),(y+2),(y+8),(y+5),(z+6),(z+3),(z+4)};

145. int []pitcharray7=

{(x+11),(x+0),(y+2),(x+8),(y+1),(y+10),(y+3),(y+9),(y+6),(z+7),(z+4),(z+5)};

146. int []pitcharray8=

{(x+0),(x+1),(y+3),(x+9),(y+2),(y+11),(y+4),(y+10),(y+7),(z+8),(z+5),(z+6)};

147. int []pitcharray9=

{(x+1),(x+2),(y+4),(x+10),(y+3),(y+0),(y+5),(y+11),(y+8),(z+9),(z+6),(z+7)};

148. int []pitcharray10=

{(x+2),(x+3),(y+5),(x+11),(y+4),(y+1),(y+6),(y+0),(y+9),(z+10),(z+7),(z+8)};

149. int []pitcharray11=

{(x+3),(x+4),(y+6),(x+0),(y+5),(y+2),(y+7),(y+1),(y+10),(z+11),(z+8),(z+9)};

150. double []rhythmarray

={4,2,1.75,1.5,1.25,1,0.75,0.5,0.25,0.333,0.2,0.125};

151. double i = rhythmarray[ randomNumber.nextInt(11)];

152. int l = randomNumber.nextInt(1000);

153. if(l%2==0){

154. phr2.addNoteList(pitcharray0,i);}

155. else if(l%3==0){

Page 111: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

156. phr2.addNoteList(pitcharray1,i);}

157. else if(l%5==0){

158. phr2.addNoteList(pitcharray2,i);}

159. else if(1%7==0){

160. phr2.addNoteList(pitcharray3,i);}

161. else if(l%11==0){

162. phr2.addNoteList(pitcharray4,i);}

163. else if(l%13==0){

164. phr2.addNoteList(pitcharray5,i);}

165. else if(l%17==0){

166. phr2.addNoteList(pitcharray6,i);}

167. else if(l%19==0){

168. phr2.addNoteList(pitcharray7,i);}

169. else if(l%23==0){

170. phr2.addNoteList(pitcharray8,i);}

171. else if(l%29==0){

172. phr2.addNoteList(pitcharray9,i);}

173. else if(l%31==0){

174. phr2.addNoteList(pitcharray10,i);}

175. else{

176. phr2.addNoteList(pitcharray11,i);}

177. int m = randomNumber.nextInt(50);

178. if (m % 2 == 0){

179. Mod.palindrome(phr2);}

180. else if (m % 3 == 0){

181. Mod.rotate(phr2);}

182. else if(m % 4 ==0){

183. Mod.inversion(phr2);}

184. else if(m % 5 ==0){

185. Mod.shake(phr2);}

186. else{

187. Mod.retrograde(phr2);}}

188.

189. p1.addPhrase(phr);

190. p2.addPhrase(phr1);

191. p3.addPhrase(phr2);

192. s.addPart(p1);

193. s.addPart(p2);

194. s.addPart(p3);

Page 112: 國立臺灣師範大學 - NTNUrportal.lib.ntnu.edu.tw/bitstream/20.500.12235/108781/1/... · 2019. 9. 6. · Varese, 1886-1965)於1934 年創作的作品 À赤道 Á(Ecuatorial,

195. Write.midi(s,"TC5.mid");

196. View.show(s);

197. Play.midi(s);}}