diff --git a/.gitignore b/.gitignore index 5fa3cae..362371b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ resources public/ -.DS_Store \ No newline at end of file +.DS_Store +content/.obsidian +node_modules \ No newline at end of file diff --git a/content/docs/2023/code-design/11/2023-code-and-design-11.pdf b/content/docs/2023/code-design/11/2023-code-and-design-11.pdf new file mode 100644 index 0000000..3dcf824 Binary files /dev/null and b/content/docs/2023/code-design/11/2023-code-and-design-11.pdf differ diff --git a/content/docs/2023/code-design/11/_index.en.md b/content/docs/2023/code-design/11/_index.en.md new file mode 100644 index 0000000..0818604 --- /dev/null +++ b/content/docs/2023/code-design/11/_index.en.md @@ -0,0 +1,13 @@ +--- +title: Week 11 +date: 2023-06-23 +weight: 11 +params: + pdf_path: 2023-code-and-design-11.pdf +--- + +# 2023 Tokyo University of the Arts Art media Center「Code and Design」 Week 11 + +## Slide + +{{< embed_pdf >}} \ No newline at end of file diff --git a/content/docs/2023/code-design/11/_index.md b/content/docs/2023/code-design/11/_index.md new file mode 100644 index 0000000..6668dcf --- /dev/null +++ b/content/docs/2023/code-design/11/_index.md @@ -0,0 +1,13 @@ +--- +title: 第11週 +date: 2023-06-23 +weight: 11 +params: + pdf_path: 2023-code-and-design-11.pdf +--- + +# 2023年 東京藝術大学 芸術情報センター開設科目 「コードとデザイン」 第11回 + +## スライド + +{{< embed_pdf >}} \ No newline at end of file diff --git a/content/docs/2023/code-design/13/_index.en.md b/content/docs/2023/code-design/13/_index.en.md new file mode 100644 index 0000000..0818604 --- /dev/null +++ b/content/docs/2023/code-design/13/_index.en.md @@ -0,0 +1,13 @@ +--- +title: Week 11 +date: 2023-06-23 +weight: 11 +params: + pdf_path: 2023-code-and-design-11.pdf +--- + +# 2023 Tokyo University of the Arts Art media Center「Code and Design」 Week 11 + +## Slide + +{{< embed_pdf >}} \ No newline at end of file diff --git a/content/docs/2023/code-design/13/_index.md b/content/docs/2023/code-design/13/_index.md new file mode 100644 index 0000000..0c79cd9 --- /dev/null +++ b/content/docs/2023/code-design/13/_index.md @@ -0,0 +1,61 @@ +--- +title: 第13週 +date: 2023-06-23 +weight: 13 +--- + +# 2023年 東京藝術大学 芸術情報センター開設科目 「コードとデザイン」 第13回 + +## スライド + +(スライド行方不明・・・多分この日はスライドなかったと思います) + +## 銅箔テープで作る平面コイルのSVGを出力するProcessingスケッチ + + + +```java +import processing.svg.*; + +void setup(){ + noLoop(); + size(800,800); + stroke(0); + background(255); + beginRecord(SVG, "spiral.svg"); + +} + +float diameter = 800; + + +void draw(){ + float angle = 0; + float r = 1; + float r_step =0.4; + float angle_step = 0.1; + translate(width/2,height/2); + float x_tmp = 0; + float y_tmp = 0; + while(r < width/2-10){ + r += r_step; + angle += angle_step; + float x = r*sin(angle); + float y = r*cos(angle); + line(x_tmp,y_tmp,x,y); + x_tmp = x; + y_tmp = y; + } + r+=9; + while(r > 0){ + r -= r_step; + angle -= angle_step; + float x = r*sin(angle); + float y = r*cos(angle); + line(x_tmp,y_tmp,x,y); + x_tmp = x; + y_tmp = y; + } +endRecord(); +} +``` \ No newline at end of file diff --git a/content/docs/2023/code-design/13/svg_spiral.pde b/content/docs/2023/code-design/13/svg_spiral.pde new file mode 100644 index 0000000..2b2c829 --- /dev/null +++ b/content/docs/2023/code-design/13/svg_spiral.pde @@ -0,0 +1,43 @@ +import processing.svg.*; + +void setup(){ + noLoop(); + size(800,800); + stroke(0); + background(255); + beginRecord(SVG, "spiral.svg"); + +} + +float diameter = 800; + + +void draw(){ + float angle = 0; + float r = 1; + float r_step =0.4; + float angle_step = 0.1; + translate(width/2,height/2); + float x_tmp = 0; + float y_tmp = 0; + while(r < width/2-10){ + r += r_step; + angle += angle_step; + float x = r*sin(angle); + float y = r*cos(angle); + line(x_tmp,y_tmp,x,y); + x_tmp = x; + y_tmp = y; + } + r+=9; + while(r > 0){ + r -= r_step; + angle -= angle_step; + float x = r*sin(angle); + float y = r*cos(angle); + line(x_tmp,y_tmp,x,y); + x_tmp = x; + y_tmp = y; + } +endRecord(); +} diff --git a/content/docs/2023/code-design/9/_index.md b/content/docs/2023/code-design/9/_index.md index 9de34d0..ad06be2 100644 --- a/content/docs/2023/code-design/9/_index.md +++ b/content/docs/2023/code-design/9/_index.md @@ -2,6 +2,8 @@ title: 第9週 date: 2023-06-09 weight: 9 +params: + pdf_path: 2023-code-and-design-9.pdf --- # 2023年 東京藝術大学 芸術情報センター開設科目 「コードとデザイン」 第9回 diff --git a/content/docs/2023/code-design/_index.md b/content/docs/2023/code-design/_index.md index 65a6128..1bc73dc 100644 --- a/content/docs/2023/code-design/_index.md +++ b/content/docs/2023/code-design/_index.md @@ -43,10 +43,10 @@ bookCollapseSection: true 7. [(5/26) 入力を考える(不条理なマウスを作る)](./7) 8. [(6/2) 入力を考える2 - ProcessingとArduinoの連携、オブジェクト指向プログラミング(一人用PONG)](./8) 9. [(6/9) 出力を考える - Arduinoでの音声プログラミング](./9) -10. (6/16) Cartesian Robotとデジタルファブリケーション (3DプリンターとGコードハック) -11. (6/23) 制作①相談 -12. (6/30) 制作②作業 -13. (7/7) 制作③ 内容に応じた補足授業 +10. (6/16) 制作①相談1 +11. [(6/23) デジタルファブリケーション:入力機器(可変抵抗)を作る](./11) +12. (6/30) 制作②相談2 +13. [(7/7) デジタルファブリケーション:出力機器(スピーカー)を作る](./13) 14. (7/14) 課題発表展示 15. (7/21) 展示撤収・発表ふりかえりとまとめ diff --git a/content/docs/2023/mediaart-programming2/1/2023-media-art-programming2-1.pdf b/content/docs/2023/mediaart-programming2/1/2023-media-art-programming2-1.pdf new file mode 100644 index 0000000..91ba0d6 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/1/2023-media-art-programming2-1.pdf differ diff --git a/content/docs/2023/mediaart-programming2/1/_index.en.md b/content/docs/2023/mediaart-programming2/1/_index.en.md new file mode 100644 index 0000000..49416b7 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/1/_index.en.md @@ -0,0 +1,15 @@ +--- +title: Week 1 +date: 2023-10-06 +weight: 1 +draft: false +params: + pdf_path: 2023-media-art-programming2-1.pdf +--- + +# 2023 Media Art Programming #1 + +## Slides + +{{< embed_pdf >}} + diff --git a/content/docs/2023/mediaart-programming2/1/_index.md b/content/docs/2023/mediaart-programming2/1/_index.md new file mode 100644 index 0000000..fd8a090 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/1/_index.md @@ -0,0 +1,14 @@ +--- +title: 第1週 +date: 2023-10-06 +weight: 1 +draft: false +params: + pdf_path: 2023-media-art-programming2-1.pdf +--- + +# 2023年 メディアアート・プログラミング 第1回 + +## スライド + +{{< embed_pdf >}} diff --git a/content/docs/2023/mediaart-programming2/10/1_launch.js b/content/docs/2023/mediaart-programming2/10/1_launch.js new file mode 100644 index 0000000..e8143e8 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/10/1_launch.js @@ -0,0 +1,12 @@ +const puppeteer = require('puppeteer'); + +const main = async () => { + let browser = await puppeteer.launch({ headless: false }); + let page = await browser.newPage(); + await page.goto('https://www.youtube.com/'); + await page.screenshot({ path: "./ss.png", fullPage: true }); + await page.close(); + await browser.close(); +}; + +main(); diff --git a/content/docs/2023/mediaart-programming2/10/2023-media-art-programming2-10.pdf b/content/docs/2023/mediaart-programming2/10/2023-media-art-programming2-10.pdf new file mode 100644 index 0000000..c18fdb4 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/10/2023-media-art-programming2-10.pdf differ diff --git a/content/docs/2023/mediaart-programming2/10/2_async_intro.js b/content/docs/2023/mediaart-programming2/10/2_async_intro.js new file mode 100644 index 0000000..0d45dac --- /dev/null +++ b/content/docs/2023/mediaart-programming2/10/2_async_intro.js @@ -0,0 +1,11 @@ +const puppeteer = require('puppeteer'); + +const main = async () => + puppeteer.launch({ headless: false }) + .then(browser => browser.newPage() + .then(page => page.goto('https://www.youtube.com/') + .then(_response => page.screenshot({ path: "./ss.png" }) + .then(_ => page.close() + .then(_ => browser.close()))))); + +main(); diff --git a/content/docs/2023/mediaart-programming2/10/3_map_async.js b/content/docs/2023/mediaart-programming2/10/3_map_async.js new file mode 100644 index 0000000..a64a962 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/10/3_map_async.js @@ -0,0 +1,21 @@ +const puppeteer = require('puppeteer'); + +const take_screen_shot = async (browser, url, index) => { + let page = await browser.newPage(); + let path = `${index}.png`; + await page.goto(url); + await page.screenshot({ path: path }); + await page.close(); +} + +const main = async () => { + let browser = await puppeteer.launch({ headless: false ,args: ["--window-size=1920,1080"],timeout:0}); + const urllist = ["https://www.youtube.com", + "https://www.google.com", + "https://www.geidai.ac.jp", + "https://yahoo.co.jp"] + await Promise.all(urllist.map((url, index) => take_screen_shot(browser, url, index))); + await browser.close(); +} + +main(); \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/10/4_auto_scroll.js b/content/docs/2023/mediaart-programming2/10/4_auto_scroll.js new file mode 100644 index 0000000..cedf0d8 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/10/4_auto_scroll.js @@ -0,0 +1,13 @@ +const puppeteer = require('puppeteer'); +const autoScroll = require("./autoscroll.js").autoScroll; + +const main = async () => { + let browser = await puppeteer.launch({ headless: false }); + let page = await browser.newPage(); + await page.goto('https://www.youtube.com/'); + await autoScroll(page,10); + await page.screenshot({ path: "ss_full.png", fullPage: true }) + await page.close(); + await browser.close(); +} +main(); \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/10/5_youtube_hopper.js b/content/docs/2023/mediaart-programming2/10/5_youtube_hopper.js new file mode 100644 index 0000000..b84bb0e --- /dev/null +++ b/content/docs/2023/mediaart-programming2/10/5_youtube_hopper.js @@ -0,0 +1,19 @@ +const puppeteer = require('puppeteer'); +const autoScroll = require("./autoscroll.js").autoScroll; + +const main = async () => { + let browser = await puppeteer.launch({ headless: false }); + let page = await browser.newPage(); + await page.goto('https://www.youtube.com/'); + for (let i = 0; i < 1000; i++) { + const urllist = await page.$$eval("a#thumbnail", elems => elems.map(elem => elem.href)); + const url = urllist[3]; + console.log(url) + await page.goto(url); + await autoScroll(page, 10); + await page.screenshot({ path: `${i}.png`, fullPage: true }); + } + await page.close(); + await browser.close(); +} +main(); \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/10/_index.en.md b/content/docs/2023/mediaart-programming2/10/_index.en.md new file mode 100644 index 0000000..6f1df02 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/10/_index.en.md @@ -0,0 +1,15 @@ +--- +title: Week 10 +date: 2023-12-08 +weight: 10 +draft: false +params: + pdf_path: 2023-media-art-programming2-10.pdf +--- + +# 2023 Media Art Programming #10 + +## Slides + +{{< embed_pdf >}} + diff --git a/content/docs/2023/mediaart-programming2/10/_index.md b/content/docs/2023/mediaart-programming2/10/_index.md new file mode 100644 index 0000000..7fbd5ff --- /dev/null +++ b/content/docs/2023/mediaart-programming2/10/_index.md @@ -0,0 +1,30 @@ +--- +title: 第10週 +date: 2023-12-08 +weight: 10 +draft: false +params: + pdf_path: 2023-media-art-programming2-10.pdf +--- + +# 2023年 メディアアート・プログラミング 第10回 + +## スライド + +{{< embed_pdf >}} + +## puppeteerのコードサンプル + +`autoscroll.js`は`4_auto_scroll.js`でライブラリとして使用するだけなので、内容を理解しなくても大丈夫です。 + +{{< preview_code href="1_launch.js" type= "js">}} + +{{< preview_code href="2_async_intro.js" type= "js">}} + +{{< preview_code href="3_map_async.js" type= "js">}} + +{{< preview_code href="4_auto_scroll.js" type= "js">}} + +{{< preview_code href="5_youtube_hopper.js" type= "js">}} + +{{< preview_code href="autoscroll.js" type= "js">}} \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/10/autoscroll.js b/content/docs/2023/mediaart-programming2/10/autoscroll.js new file mode 100644 index 0000000..f6b83d5 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/10/autoscroll.js @@ -0,0 +1,18 @@ +async function autoScroll(page, maxScrolls) { + await page.evaluate(async maxScrolls => { + await new Promise((then) => { + let distance = 1000; + let scrolls = 0; + let timer = setInterval(() => { + window.scrollBy(0, distance); + scrolls += 1; + if (scrolls >= maxScrolls) { + clearInterval(timer); + then(); + } + }, 100); + }); + }, maxScrolls); +} + +exports.autoScroll = autoScroll; \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/10/package.json b/content/docs/2023/mediaart-programming2/10/package.json new file mode 100644 index 0000000..db610a4 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/10/package.json @@ -0,0 +1,15 @@ +{ + "name": "20231201-scraping_test", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "jsdom": "^23.0.1", + "puppeteer": "^21.6.0", + } +} \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/2/2023-media-art-programming2-2.pdf b/content/docs/2023/mediaart-programming2/2/2023-media-art-programming2-2.pdf new file mode 100644 index 0000000..8438184 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/2/2023-media-art-programming2-2.pdf differ diff --git a/content/docs/2023/mediaart-programming2/2/_index.en.md b/content/docs/2023/mediaart-programming2/2/_index.en.md new file mode 100644 index 0000000..83d13c0 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/2/_index.en.md @@ -0,0 +1,15 @@ +--- +title: Week 2 +date: 2023-10-13 +weight: 2 +draft: false +params: + pdf_path: 2023-media-art-programming2-2.pdf +--- + +# 2023 Media Art Programming #2 + +## Slides + +{{< embed_pdf >}} + diff --git a/content/docs/2023/mediaart-programming2/2/_index.md b/content/docs/2023/mediaart-programming2/2/_index.md new file mode 100644 index 0000000..61364aa --- /dev/null +++ b/content/docs/2023/mediaart-programming2/2/_index.md @@ -0,0 +1,14 @@ +--- +title: 第2週 +date: 2023-10-13 +weight: 2 +draft: false +params: + pdf_path: 2023-media-art-programming2-2.pdf +--- + +# 2023年 メディアアート・プログラミング 第2回 + +## スライド + +{{< embed_pdf >}} diff --git a/content/docs/2023/mediaart-programming2/3/2023-media-art-programming2-3.pdf b/content/docs/2023/mediaart-programming2/3/2023-media-art-programming2-3.pdf new file mode 100644 index 0000000..8ffcd74 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/2023-media-art-programming2-3.pdf differ diff --git a/content/docs/2023/mediaart-programming2/3/_index.en.md b/content/docs/2023/mediaart-programming2/3/_index.en.md new file mode 100644 index 0000000..77a08cd --- /dev/null +++ b/content/docs/2023/mediaart-programming2/3/_index.en.md @@ -0,0 +1,18 @@ +--- +title: Week 3 +date: 2023-10-20 +weight: 3 +params: + pdf_path: 2023-media-art-programming2-3.pdf +draft: false +--- + +# 2023 メディアアート・プログラミング Week 3 + +## Slides + +{{< embed_pdf >}} + +{{< button href=.Page.Params.pdf_path >}}Slides(PDF){{< /button >}} + +{{< button href="slides">}}Slides(HTML){{< /button >}} diff --git a/content/docs/2023/mediaart-programming2/3/_index.md b/content/docs/2023/mediaart-programming2/3/_index.md new file mode 100644 index 0000000..a95431c --- /dev/null +++ b/content/docs/2023/mediaart-programming2/3/_index.md @@ -0,0 +1,18 @@ +--- +title: 第3週 +date: 2023-10-20 +weight: 3 +draft: false +params: + pdf_path: 2023-media-art-programming2-3.pdf +--- + +# 2023年 メディアアート・プログラミング 第3回 + +## スライド + +{{< embed_pdf >}} + +{{< button href=.Page.Params.pdf_path >}}スライド(PDF){{< /button >}} + +{{< button href="slides">}}スライド(HTML){{< /button >}} diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.001.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.001.jpeg new file mode 100644 index 0000000..4a05c85 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.001.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.002.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.002.jpeg new file mode 100644 index 0000000..96e42d4 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.002.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.003.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.003.jpeg new file mode 100644 index 0000000..d9f95e7 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.003.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.004.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.004.jpeg new file mode 100644 index 0000000..ad88b90 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.004.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.005.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.005.jpeg new file mode 100644 index 0000000..9d05625 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.005.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.006.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.006.jpeg new file mode 100644 index 0000000..4c40896 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.006.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.007.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.007.jpeg new file mode 100644 index 0000000..5e2c44f Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.007.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.008.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.008.jpeg new file mode 100644 index 0000000..3662147 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.008.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.009.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.009.jpeg new file mode 100644 index 0000000..28f3edc Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.009.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.010.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.010.jpeg new file mode 100644 index 0000000..3066b31 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.010.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.011.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.011.jpeg new file mode 100644 index 0000000..e9f2277 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.011.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.012.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.012.jpeg new file mode 100644 index 0000000..cbb7bfd Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.012.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.013.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.013.jpeg new file mode 100644 index 0000000..6b07172 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.013.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.014.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.014.jpeg new file mode 100644 index 0000000..94ac383 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.014.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.015.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.015.jpeg new file mode 100644 index 0000000..b04e519 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.015.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.016.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.016.jpeg new file mode 100644 index 0000000..608610a Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.016.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.017.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.017.jpeg new file mode 100644 index 0000000..ccfbcd2 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.017.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.018.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.018.jpeg new file mode 100644 index 0000000..b7b2d9f Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.018.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.019.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.019.jpeg new file mode 100644 index 0000000..1da4cc8 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.019.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.020.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.020.jpeg new file mode 100644 index 0000000..4d55d92 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.020.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.021.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.021.jpeg new file mode 100644 index 0000000..7ae0e6e Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.021.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.022.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.022.jpeg new file mode 100644 index 0000000..7806616 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.022.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.023.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.023.jpeg new file mode 100644 index 0000000..0232c64 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.023.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.024.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.024.jpeg new file mode 100644 index 0000000..ce59bac Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.024.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.025.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.025.jpeg new file mode 100644 index 0000000..9361595 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.025.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.026.jpeg b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.026.jpeg new file mode 100644 index 0000000..585a432 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/3/slides/2023-media-art-programming2-3.026.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/3/slides/index.en.md b/content/docs/2023/mediaart-programming2/3/slides/index.en.md new file mode 100644 index 0000000..afde317 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/3/slides/index.en.md @@ -0,0 +1,10 @@ +--- +title: Media Art Programming 2023 Week 3 Slides +date: 2023-10-20 +bookHidden: true +--- + + +# Slides + +{{< slides_jpg >}} \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/3/slides/index.md b/content/docs/2023/mediaart-programming2/3/slides/index.md new file mode 100644 index 0000000..14791cb --- /dev/null +++ b/content/docs/2023/mediaart-programming2/3/slides/index.md @@ -0,0 +1,10 @@ +--- +title: メディアアートプログラミング 2023年 第3回 スライド +date: 2023-10-20 +bookHidden: true +--- + + +# スライド + +{{< slides_jpg >}} \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/4/2023-media-art-programming2-4.pdf b/content/docs/2023/mediaart-programming2/4/2023-media-art-programming2-4.pdf new file mode 100644 index 0000000..b812aa8 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/2023-media-art-programming2-4.pdf differ diff --git a/content/docs/2023/mediaart-programming2/4/_index.en.md b/content/docs/2023/mediaart-programming2/4/_index.en.md new file mode 100644 index 0000000..7033d65 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/4/_index.en.md @@ -0,0 +1,477 @@ +--- +title: Week 4 +date: 2023-10-27T16:40:01+09:00 +weight: 4 +params: + pdf_path: "2023-media-art-programming2-4.pdf" +--- + +# 2023 Media Art Programming 4th + +## Slides + +{{< embed_pdf >}} + +{{< button href=.Page.Params.pdf_path >}} slides (PDF) {{< /button >}} + +{{< button href="slides">}}slides (HTML){{< /button >}} + +## Shells and Pipes + +Previously we have used basic commands such as `ls` and `cd`, which take terminal text input and return text output to the terminal. + +On Unix-like operating systems, the input and output of commands with simple functions can be combined to perform complex operations using a feature called **pipes**. + +Take, for example, the command `say`, which can be used on macOS to read text aloud. + +The following command will cause macOS to say "Hello" aloud. + +```sh +say "Hello". +``` + +Here, a program called say receives the text `"hello"` from **standard input (stdin)**. + +So what happens if there is no input at all? + +```sh +say +``` + +When executed without input, the say command enters a mode in which it waits for text input. Here, typing "hello" and then pressing the Enter key will cause the command to read out the text. When it finishes reading, it waits for text input again. + +Standard input is often given in the form of a first argument or otherwise entered by the user from the terminal when the program is executed. + +A pipe can be used here to pass the result of another command to say as standard input. + +```sh +echo "hello" | say +``` + +The `echo`` command simply writes arbitrary text to standard output, while ``say`` is executed without arguments as before, but instead of going into interactive mode, it reads the "hello" given by ``echo` and exits. + +Instead of `echo`, you can use a command that writes a file to standard output, such as `cat hogehoge.txt`, to read an arbitrary text file. + +## Files and Devices + +By the way, files on storage are not the only things that `cat` can open; Unix-like operating systems can also take hardware information on your computer (e.g., CPU temperature, hard disk RPM, etc.) just as they can handle files. + +These devices reside in the `/dev` directory. This directory is not accessible from the Finder. + +```sh +ls /dev +``` + +There are many devices out there, but it is difficult to guess their contents from their names. Let's try to use `urandom`, a hardware random number generator on your computer. + +On computers, random numbers are often treated as algorithmic sequences of numbers, which means that knowing the initial value of a random number can predict subsequent random number sequences, so security-critical random number generation is often based on time or hardware random number generators. + +Since opening with `cat` produces a tremendous number of random numbers and causes the terminal to freeze, let's use the head command to extract only the first few lines. Since `urandom` writes out random numbers as binary, it will include many that cannot be encoded as strings. + +```sh +head /dev/urandom +``` + +And although not available today, in the past Linux had a virtual device called `/dev/dsp` that could write waveform data directly to the audio driver when written via pipe. Currently in Linux, the command `aplay` can do the same thing. + +There is an attempt to take advantage of this mechanism, called **Bytebeat**, to generate sound in as short and simple a program as possible. + +## Bytebeat + +{{< youtube tCRPUv8V22o>}} + +Bytebeat was first published by viznut in 2011 in a video on Youtube, which spread through commentary on his blog. + +[Algorithmic symphonies from one line of code -- how and why?(2011)](http://countercomplex.blogspot.com/2011/10/algorithmic-symphonies-from- one-line-of.html) + +Later, several environments were created that allow similar code to be executed on a web browser. + +https://greggman.com/downloads/examples/html5bytebeat/html5bytebeat.html + +https://sarpnt.github.io/bytebeat-composer + + +Let's try Bytebeat the old-fashioned (?) way of actually creating binary data. Let's try it the old-fashioned (?) way of actually creating binary data. + +Bytebeat was originally created with the following C program. + +```c +main(t){for(;;t++)putchar(((t<<1)^((t<<1)+(t>>7)&t>>12))|t>>(4-(1^7&(t>>>19)))|t>>7);} +``` + +This C code is compressed to the extreme, so if we write it a little more carefully, it looks like this + +```c +int main(int t){ + for(;;t++){ + putchar(((t<<1)^((t<<1)+(t>>7)&t>>12))|t>>(4-(1^7&(t>>>19)))|t>>7); + } +} +``` + +C program defines a function called `main`, which is the entrance to be executed by the program. +In an infinite loop with `for`, `t` starts at 0 at the beginning of the program and is increased by 1 for each loop. So this is the virtual time. + +`putchar` is one of the most primitive functions in C, writing a single byte of data to the standard output. +When this t is calculated with various operations, one byte of data (0~255) is output as the value of one sample waveform (≈voltage, air pressure). + +Data written to `/dev/dsp` is interpreted as 1 byte 1 sample with a sampling rate of 8000 Hz. + +This time, we will use Node.js instead of C, which is difficult to build an environment for, and a program called `ffmpeg` so that it can be run outside of Linux. + +## What is ffmpeg? + +`ffmpeg` is a tool for converting files and data streams of various formats. +For example, you can convert a wav file to an mp3 file, receive internet radio and export it to a file, or conversely, play an audio file and host internet radio. + +Because of its modularity and ability to convert so many different formats, it is no exaggeration to say that ffmpeg is behind most of the distribution services in the world. + +### Installing ffmpeg + +You can install `ffmpeg` with Homebrew. Please note that it takes a long time because of many dependent libraries. + +```sh +brew install ffmpeg +``` + +### ffmpeg and ffplay commands + +When you install `ffmpeg`, you can use the command `ffplay` at the same time. + +ffplay` is a universal audio/video playback tool that allows you to play the second part of ffmpeg on your system instead of exporting or streaming files. + +For example, you can use the following commands to play a normal audio file. + +```sh +ffplay hoge.wav +``` + +You can also listen to Internet radio. You can receive NHK-FM (Tokyo) by opening the following URL. [^nhkurl] + +[^nhkurl]: You can get a list of URLs for NHK web radio here. http://www.nhk.or.jp/radio/config/config_web.xml + +```sh +ffplay https://radio-stream.nhk.jp/hls/live/2023507/nhkradiruakfm/master.m3u8 +``` + +During playback, the standard view of the frequency distribution is the spectrogram. + +![Screenshot of playback while displaying the spectrogram in ffplay...](radio1.png) + +Pressing the w key with focus on this window allows you to switch between modes of waveform display. [^view] + +[^view]: Optionally, `-showmode 0` will display 0: video (hidden for audio files), 1: waveform, 2: spectrogram. + + +![Screenshot of the audio waveform being played while it is displayed by ffplay]. (radio2.png) + +### Listening to Audacity with ffmpeg + +Last time, we did "Listen to Audacity with Audacity". If you do that again with ffplay, you will get the following command. + +```sh +cat '/Applications/Audacity.app/Contents/MacOS/Audacity' | ffplay -f u8 -i pipe:0 -ar 44k -ac 1 +``` + +This time, let's interpret the data as 1 byte per sample, the sample rate as 44100 (can be abbreviated as 44k), and the number of audio channels as mono. +Normally, ffplay infers the format of the data from the file extension or file header, but this time, since it reads the raw data directly, we need to specify the format as an option. This option corresponds directly to the "Import Raw Data" option we used in Audacity. + +![](slides/2023-media-art-programming2-4.011.jpeg) + +## Manipulate byte strings with Javascript! + +We've piped the raw byte data into ffplay and listened to it. Now it's time to create the code to generate the byte data. + +Javascript inherently makes no distinction between numeric byte sizes, etc. (everything is handled in real numbers, 64-bit floating point format in many environments). + +The only way to handle numerical data with a defined type is by using an array with a specified type, in this case `Uint8Array`. + +With this method, it is a little difficult to continuously write to standard output, so let's first write the binary data to a file once, and then read it out with cat and pipe it as before. + +The minimum program to create Bytebeat this time is as follows. + +```js {title = "bytebeat.js"} +const fs = require("fs"); +const sample_rate = 8000; +const seconds = 5; +const byte_length = sample_rate*seconds; +const bytebeat = t => + (t*(1+(5&t>10))*(3+(t>>17&1?(2^2&t>14)/3:3&(t>>13)+1))>>(3&t>9))&(t&4096?(t*(t^t%9)|t>3)>>1:255); + +const data = Uint8Array.from({ length: byte_length },. + (v, t) => bytebeat(t) +); +fs.writeFile("jsbytebeat.hex",data, err => {} ); +``` + +Let's look at them in turn. + +```js +const fs = require("fs"); +``` + +This line is loading the library for the final file write. Don't worry about it too much. + +```js +const sample_rate = 8000; +const seconds = 5; +const byte_length = sample_rate*seconds; +``` +The first two lines specify the sampling rate (how many samples per second of resolution to pack into the data) and the length of the audio waveform to be generated in seconds. +Once these two values are determined, you know how many bytes of data should be generated in the end. That is the `length`. + +``js +const bytebeat = t => + (t*(1+(5&t>10))*(3+(t>>17&1?(2^2&t>14)/3:3&(t>>13)+1))>>(3&t>>9))&(t&4096?(t*(t^t%9)|t>3)>>1:255); +``` + +This line is the Bytebeat program that will eventually generate the waveform. This writing style using `=>` is an abbreviation of the function definition. + +```js +function bytebeat(t) { + return (t*(1+(5&t>10))*(3+(t>>17&1?(2^2&t>14)/3:3&(t>>13)+1))>>(3&t>>9))&(t&4096?(t*(t^t%9)|t>3)>>1:255); +} +``` +This definition is exactly the same. The way it is written is a matter of taste, but note that return can only be omitted in the above way (even in the above way, return is still required if the `=>` is followed by curly braces `{}`). + + +``js +const data = Uint8Array.from({ length: byte_length },. + (v, t) => bytebeat(t) +); +``` +Now we create an array of unsigned 8-bit integers. There are many ways to do this, but in this case we will use the `from`` method with the ``length` and the initialization function. + +In `{length:byte_length}` we specify that we want to create an array of 8000*5=400000 samples calculated earlier. + + `(v, t) => bytebeat(t)` is an initialization process that takes the index of an array called t, puts it into the bytebeat function, and stores the converted values in the array in order. + +```js. +fs.writeFile("jsbytebeat.hex",data, err => {} ); +``` + +Here we finally save the resulting byte sequence. The third argument, `err => {}`, indicates that no action is to be taken in error handling. The third argument, `err => {}`, refers to doing nothing in error handling. + +Now, let's run this as `bytebeat.js` in the terminal. +At this time, remember that the `-ar` option in ffplay should match the sampling rate specified in the source code. + + +```sh +node bytebeat.js +cat jsbytebeat.hex | ffplay -f u8 -i pipe:0 -ar 8k -ac 1 +``` + +If all goes well, 5 seconds of audio should play and stop. + +You can also use ffmpeg instead of ffplay to output it again as a wav file. + +```sh +cat jsbytebeat.hex | ffmpeg -f u8 -ar 8k -i pipe:0 -c:a pcm_u8 -ac 1 -y jsbytebeat.wav +``` + + +### Let's take a quick look at the waveforms. + +Let's try the bytebeat function as a function that just returns t as it is. + +```js +const bytebeat = t => + t +``` + +In this case, the value of t itself keeps rising without limit up to several hundred thousand and so on, but when it is finally written to `Uint8Array`, only the lower 8 bits of the integer portion are written. What this means is that after rising from 0 to 255, it returns to 0 again. + +If you open this `jsbytebeat.hex` with 0~255 written in it with VSCode's Hex Editor, it looks like the following. + +![Visual Studio Code screenshot showing binary data with continuous 0~255 in the Binary Editor]. (binary.png) + +You can see that the numbers rise in sequence from 00 to FF (255) and back to 00 again. + +However, it is difficult to understand what kind of waveform is being generated just by looking at the binary directly in the Hex Editor. + +You can export the data to ffmpeg and view it in Audacity, or use ffplay's waveform display mode, but since we are here, let's plot the data in a simple way. + +Add the following line to the second half of bytebeat.js as shown above. + +```js +let file = fs.createWriteStream("graph.txt"); +for (byte of data){ + let txt = ""; + for (i = 0; i < byte; i++) { + txt += "|"; } + } + txt += "\n"; } + file.write(txt); +} +file.end(); } +``` + +The above code reads one byte of the `data` array, writes a character (|) for the numeric value of the data, breaks the line, reads the next byte again ......, and repeats to create a file called graph.txt. + +Now when you run `node bytebeat.js` again, it will create `graph.txt` in the directory. + +If you open this in VSCode, it should look like this. + +![](graph.png) + +Although the display will vary depending on the size of the characters and the text wrapping settings, a sawtooth waveform is plotted by increasing the number of characters by one per line. + +### Let's make it possible to run the program continuously. + +Writing the contents of a `Uint8Array` to standard output is relatively easy with `process.stdout.write(data)`, but it is surprisingly troublesome to make it continue to do so permanently. + +For now, let's change the code that just generated the array so that it can be written to standard output. + +```js + const data = Uint8Array.from({ length: length }, + (v, t) => bytebeat(t) + ); + process.stdout.write(data); +``` + +Let's call this file `bytebeat_stream.js`. +Now we can pipe the output of node directly and play it back for 5 seconds. + +```sh +node bytebeat_stream.js | ffplay -f u8 -i pipe:0 -ar 8k -ac 1 +``` + +Eventually I want to be able to do this continuously, so I'll create an infinite loop like this. + +```js +while(true){ + const data = Uint8Array.from({ length: length },. + (v, t) => bytebeat(t) + ); + process.stdout.write(data); +} +``` + +There are two problems with this code: first, t is an index created during array creation, so it resets to 0 every 5 seconds. Therefore, t should be defined as a global variable on the outside and updated. + +```js +let t = 0; +while(true){ + const data = Uint8Array.from({ length: length }, + (v, _t) => { + const res = bytebeat(t); + t++; + return res; + } + ); + process.stdout.write(data); +} +``` + +Declare `t` with `let` instead of `const` to declare it as a variable to be rewritten later. + +Also, the argument `(v,t)` used to generate the original array is no longer used, so change it to `_t` so that the name is not covered by the variable `t`. + +Another problem is that the speed at which the byte sequence is generated is by far faster than it is actually consumed by the audio driver. +(This is also the specification of the original C program, so you don't have to worry about it too much, but...) If unused data is generated endlessly and passed through a pipe, it can eat up a lot of memory. +There are several ways to achieve this, but a simple way is to use the `setInterval` function, which keeps executing a specific function at a fixed interval. + +First, the part of the code that writes to standard output for 5 seconds should be a function called `mainProcess`. + +```js +const mainProcess = ()=> { + const data = Uint8Array.from({ length: length }, + (v, _t) => { + const res = bytebeat(t); + t += 1; + return res + } + ); + process.stdout.write(data); +}; +``` +This is specified in `setInterval`. The second argument specifies the interval between executions, and the unit of the number at this time is milliseconds. So, divide the number of seconds specified in `seconds` by 1000. + +```js +setInterval(mainProcess,seconds / 1000.0); +``` + +In practice, the `mainProcess` should take some time to execute, so if you are generating exactly 5 seconds and waiting for 5 seconds, there may be cases where the audio driver fails because there is not enough data to write to the audio driver. In such cases, you may want to use `1010.0` instead of `1000.0` to speed up the execution. + +That's how the finished version of `bytebeat_stream.js` looks like this + +```js +const sample_rate = 8000; +const seconds = 1; +const length = sample_rate * seconds; +const bytebeat = t => + (((t >> 10 ^ t >> 11) % 5) * t >> 16) * ((t >> 14 & 3 ^ t >> 15 & 1) + 1) * t % 99 + ((3 + (t >> 14 & 3) - (t >> 16 & 1)) / 3 * t % 99 & 64); +let t = 0; + +const mainProcess = () =>{ + const data = Uint8Array.from({ length: length }, + (v, _t) => { + const res = bytebeat(t); + t += 1; + return res + } + ); + process.stdout.write(data); +}; + +setInterval(mainProcess,seconds / 1000.0); +``` + + + +## Supplemental (memorandum) + +### Handling of integer operations in Javascript + +It is actually not so obvious that the conversion of numeric types when finally packing integer values into a Uint8Array in JS is the same as in Bytebeat in C. + +For example, if you open a Node.js REPL and do some calculations, + +``` +> 1<<30 +1073741824 +> 1<<31 +-2147483648 +> 1<<32 +1 + +> (1<<31)+0.1 +-2147483647.9 +> 1.1<<31 +-2147483648 +> 0.9<<31 +0 + +> 2 ** 52 +4503599627370496 +> 2**52+1 +4503599627370497 +> 2 ** 53 +9007199254740992 +> 2 ** 53 +1 +9007199254740992 +``` + +and so on. From here, without looking up the specification, we can roughly do the following + +- The internal representation of numbers in JS is 64-bit floating point (`double` in C). +- The mantissa part (integer value when the exponent part is 0) is signed 53bit (if you take out the upper 32bit, it becomes C's `int`/`int32_t`). +- When performing bitwise operations, once truncate to an integer, and then calculate as an operation between signed 32 bits. +- When putting into `Uint8Array` and so on, the lower bits are cut out and casted, and the lower 32 bits are also used when casted from a 52-bit integer to a 32-bit integer. + +I checked later and it seems that this specification is generally correct. + +This behavior seems to eventually lead to the same result as the case where `t` is cast to type `char` when doing `putchar` using the first argument of the `main` function, that is, `int`, when doing Bytebeat in C language. + +It seems to be established on the balance of quite exquisite specification that the same sound can be easily made in C and Javascript. I'm not sure if they were anticipating that much or not... + +However, if you think about it, when you update the time in t++, it seems that in JavaScript, after being added up to 2^52, the increment will continue with a loss of precision instead of returning to 0. For example, how much does the accuracy start to drop for mono at a sample rate of 44.1 kHz? + +```sh +> (2**52 /44100)/(60*60*24*365) +3238.2813460788693 +``` + +It looks like we have nothing to worry about for 3238 years. + + diff --git a/content/docs/2023/mediaart-programming2/4/_index.md b/content/docs/2023/mediaart-programming2/4/_index.md new file mode 100644 index 0000000..4be5082 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/4/_index.md @@ -0,0 +1,476 @@ +--- +title: 第4週 +date: 2023-10-27T16:40:01+09:00 +weight: 4 +params: + pdf_path: "2023-media-art-programming2-4.pdf" +--- + +# 2023年 メディアアート・プログラミング 第4回 + +## スライド + +{{< embed_pdf >}} + +{{< button href=.Page.Params.pdf_path >}}スライド(PDF){{< /button >}} + +{{< button href="slides">}}スライド(HTML){{< /button >}} + +## シェルとパイプ + +前回まで`ls`や`cd`のような基礎コマンドを使ってきましたが、これらはターミナルのテキスト入力を受け取るとターミナルにテキスト出力を返すものでした。 + +Unix系のOSでは、単純な機能を持つコマンドの入出力を**パイプ**と呼ばれる機能を使い、組み合わせて複雑な処理を実行できます。 + +例えばmacOSで使えるテキストを音声で読み上げるコマンド`say`を例にしましょう。 + +次のコマンドを実行すると、macOSが音声で”こんにちは”と喋ってくれます。 + +```sh +say "こんにちは" +``` + +ここでは、sayというプログラムが**標準入力(stdin)**から`"こんにちは"`というテキストを受け取っています。 + +では、入力が全くないとどうなるでしょうか? + +```sh +say +``` + +このように入力なしで実行すると、sayコマンドはテキスト入力を待機するモードになります。ここで、"こんにちは"と入力してからEnterキーを押すと読み上げが発生します。読み上げ終わると再度テキスト入力を待機します。 + +標準入力は多くの場合、第1引数の形で与えられるか、そうでなければプログラム実行時にユーザーがターミナルから入力するような形をとります。 + +ここでパイプを使うと、別のコマンドの結果を標準入力としてsayに渡すことができます。 + +```sh +echo "こんにちは" | say +``` + +`echo`は単に任意のテキストを標準出力に書き込むコマンドです。sayは先ほど同様に引数なしで実行しましたが、対話モードにはならず`echo`から与えられた"こんにちは"を読んで終了します。 + +`echo`の代わりに`cat hogehoge.txt`のようなファイルを標準出力に書き出すコマンドを使えば、任意のテキストファイルを読み上げさせることもできます。 + +## ファイルとデバイス + +ところで、`cat`が開けるものはストレージ上のファイルだけではありません。Unix系のOSはファイルを扱うのと同じようにコンピューター上のハードウェア情報(例えばCPUの温度や、ハードディスクの回転数など)を取ることもできます。 + +こうしたデバイスは`/dev`ディレクトリに存在します。このディレクトリはFinderなどから覗くことはできません。 + +```sh +ls /dev +``` + +たくさんのデバイスがありますが、名前から内容を推測することは難しいです。Bluetoothで繋がってるデバイスなどはその片鱗が伺えます。ここでは試しに、コンピューター上に搭載されているハードウェア乱数生成機`urandom`を使ってみましょう。 + +コンピューター上では乱数をアルゴリズミックな数列として扱うことが多いですが、これは乱数の初期値を知っていると続く乱数列を予測できてしまうことでもあるため、セキュリティ的に重要な乱数の生成は時刻やハードウェア乱数生成機を元に使うことが多いのです。 + +`cat`で開くとものすごい数の乱数が出てターミナルが固まってしまうので、最初の数行だけを取り出すheadコマンドを使ってみましょう。`urandom`はバイナリとしての乱数を書き出すため、文字列としてエンコードできないものもたくさん含まれてきます。 + +```sh +head /dev/urandom +``` + +そして、現在は使えないものの、昔のLinuxには`/dev/dsp`という、パイプで書き込むと直接オーディオドライバに波形データを書き込める仮想デバイスが存在しました。現在Linuxでは`aplay`というコマンドで同様のことができます。 + +この仕組みを活用して、できるだけ短く単純なプログラムで音を生成する**Bytebeat**という試みがあります。 + +## Bytebeat + +{{< youtube tCRPUv8V22o>}} + +Bytebeatは2011年にviznutがYoutube上の動画で公開し、自身のブログの解説などで広がっていったものです。 + +[Algorithmic symphonies from one line of code -- how and why?(2011)](http://countercomplex.blogspot.com/2011/10/algorithmic-symphonies-from-one-line-of.html) + +その後、Webブラウザ上でも同様のコードを実行できる環境がいくつか誕生しました。 + +https://greggman.com/downloads/examples/html5bytebeat/html5bytebeat.html + +https://sarpnt.github.io/bytebeat-composer + + +今回はBytebeatを、実際にバイナリデータを作る昔ながらの(?)やり方でやってみましょう。 + +Bytebeatは元々次のようなC言語のプログラムで作られていました。 + +```c +main(t){for(;;t++)putchar(((t<<1)^((t<<1)+(t>>7)&t>>12))|t>>(4-(1^7&(t>>19)))|t>>7);} +``` + +このC言語のコードは極限まで圧縮されているのでもうちょっと丁寧に書くとこうなります。 + +```c +int main(int t){ + for(;;t++){ + putchar(((t<<1)^((t<<1)+(t>>7)&t>>12))|t>>(4-(1^7&(t>>19)))|t>>7); + } +} +``` + +C言語のプログラムは`main`という関数を定義するとそれがプログラムで実行される入り口になります。 +`for`による無限ループの中で、`t`がプログラム開始時には0でスタートし、ループごとに1増えています。これが仮想的な時間になるわけですね。 + +`putchar`は標準出力に1バイトのデータを書き込む、C言語の中でも最も原始的な関数の1つです。 +このtを様々な演算で計算すると、1バイト分のデータ(0~255)がある1サンプルの波形の値(≒電圧、空気圧)になって出力されます。 + +`/dev/dsp`に書き込んだデータは1バイト1サンプル、サンプリングレート8000Hzとして解釈されます。 + +今回は、環境構築が大変なC言語の代わりにNode.jsを使い、Linux以外でも実行できるように`ffmpeg`というプログラムを使用します。 + +## ffmpegとは + +`ffmpeg`は様々なフォーマットのファイルやデータストリームを変換するためのツールです。 +例えばwavファイルをmp3ファイルに変換したり、インターネットラジオを受信してファイルに書き出したり、逆に音声ファイルを再生してインターネットラジオをホストするようなこともできます。 + +非常に多種多様なフォーマットの変換が可能でモジュラーな作りになっているため、世の配信サービスの裏側では大抵ffmpegが動いていると思っても過言ではありません。 + +### ffmpegのインストール + +`ffmpeg`はHomebrewでインストールできます。依存ライブラリが多いため時間がかかるので注意してください。 + +```sh +brew install ffmpeg +``` + +### ffmpegとffplayコマンド + +`ffmpeg`をインストールすると、`ffplay`というコマンドも同時に使えるようになります。 + +`ffplay`はffmpegの後段をファイル書き出しやストリーミングではなくシステム上で再生するようにした、いわば万能オーディオ/ビデオ再生ツールです。 + +例えば普通のオーディオファイルの再生は次のようなコマンドで可能です。 + +```sh +ffplay hoge.wav +``` + +また、インターネットラジオも聞けます。以下のURLを開くとNHK-FM(東京)を受信できます。[^nhkurl] + +[^nhkurl]: NHKのWebラジオのURL一覧はここから取得できます。 http://www.nhk.or.jp/radio/config/config_web.xml + +```sh +ffplay https://radio-stream.nhk.jp/hls/live/2023507/nhkradiruakfm/master.m3u8 +``` + +再生中は標準ではスペクトログラムという周波数分布のビューが表示されます。 + +![ffplayでスペクトログラムを表示しながら再生している様子のスクリーンショット。](radio1.png) + +このウィンドウにフォーカスをした状態でwキーを押すと、波形表示のモードと切り替えができます。[^view] + +[^view]: オプションで`-showmode 0`のようにすると0:ビデオ(音声ファイルの場合非表示)、1:波形、2:スペクトログラム が表示されます。 + + +![ffplayで音声波形を表示しながら再生している様子のスクリーンショット。](radio2.png) + +### Audacityをffmpegで聴く + +前回、「AudacityでAudacityを聴く」というのをやりました。あれをもう一度ffplayでもやると次のようなコマンドになります。 + +```sh +cat '/Applications/Audacity.app/Contents/MacOS/Audacity' | ffplay -f u8 -i pipe:0 -ar 44k -ac 1 +``` + +今回は、データを1バイト1サンプル、サンプルレートは44100(44kと省略できます)、オーディオチャンネル数はモノラルとして解釈しましょう。 +通常、ffplayは拡張子やファイルのヘッダーからデータのフォーマットを推定しますが、今回は生のデータを直接読むので、オプションとしてフォーマットを指定してあげる必要があります。このオプションは、前回Audacityでやった時の"Rawデータをインポート"のオプションと直接的に対応しています。 + +![](slides/2023-media-art-programming2-4.011.jpeg) + +## Javascriptでバイト列を操作しよう + +生のバイトデータをffplayにパイプして聴くことはできました。それではいよいよバイトデータを生成するコードを作っていきましょう。 + +Javascriptは本来、数値のバイトサイズなどの区別がありません(全て実数、多くの環境では64bit浮動小数点のフォーマットで扱われます)。 + +唯一、数値データの型を決めて扱う方法として、型を指定した配列、今回の場合は`Uint8Array`を使うことで実現できます。 + +この方法だと連続して標準出力に書き込み続けるのが少し難しいため、まず一度ファイルにバイナリデータを書き出して、それを先ほどと同じくcatで読み出してパイプしてみましょう。 + +今回Bytebeatを作る最小のプログラムは次のようなものになります。 + +```js {title = "bytebeat.js"} +const fs = require("fs"); +const sample_rate = 8000; +const seconds = 5; +const byte_length = sample_rate*seconds; +const bytebeat = t => + (t*(1+(5&t>>10))*(3+(t>>17&1?(2^2&t>>14)/3:3&(t>>13)+1))>>(3&t>>9))&(t&4096?(t*(t^t%9)|t>>3)>>1:255); + +const data = Uint8Array.from({ length: byte_length }, + (v, t) => bytebeat(t) +); +fs.writeFile("jsbytebeat.hex",data, err => {} ); +``` + +順番にみていきましょう。 + +```js +const fs = require("fs"); +``` + +この行は、最終的にファイル書き込みをするためのライブラリの読み込みです。あまり気にしなくても大丈夫です。 + +```js +const sample_rate = 8000; +const seconds = 5; +const byte_length = sample_rate*seconds; +``` +はじめ2行は、サンプリングレート(1秒間あたり何サンプルの解像度でデータを詰め込むか)の指定、生成する音声波形の長さを何秒にするかを決めています。 +この2つの値が決まれば、データを最終的に何バイト生成すればいいかがわかります。それが`length`です。 + +```js +const bytebeat = t => + (t*(1+(5&t>>10))*(3+(t>>17&1?(2^2&t>>14)/3:3&(t>>13)+1))>>(3&t>>9))&(t&4096?(t*(t^t%9)|t>>3)>>1:255); +``` + +この行が最終的に波形を生成するBytebeatのプログラムです。この`=>`を使う書き方は関数定義の省略形です。 + +```js +function bytebeat(t) { + return (t*(1+(5&t>>10))*(3+(t>>17&1?(2^2&t>>14)/3:3&(t>>13)+1))>>(3&t>>9))&(t&4096?(t*(t^t%9)|t>>3)>>1:255); +} +``` +この定義でも全く同じです。書き方は好みですが、returnを省略できるのは上の書き方の方だけなので注意してください(上の書き方でも、`=>`の後を中括弧`{}`で囲む場合は、やはりreturnが必須です)。 + + +```js +const data = Uint8Array.from({ length: byte_length }, + (v, t) => bytebeat(t) +); +``` +ここでunsigned 8bit 整数の配列を作成します。やり方にはいろいろありますが、今回は`from`メソッドで`length`と初期化関数を指定する方法を使いましょう。 + +`{length:byte_length}`では先ほど計算した8000*5=40000サンプル分の配列を生成することを指定しています。 + + `(v, t) => bytebeat(t)`は、tという配列のインデックスを取得してbytebeat関数に入れて変換したものを配列に順番に収めていく、という初期化の処理です。 + +```js +fs.writeFile("jsbytebeat.hex",data, err => {} ); +``` + +ここでようやく、出来上がったバイト列を保存します。`"jsbytebeat.hex"`は好きなファイル名で問題ありませんが、特にフォーマットの決まっていないバイナリファイルなら拡張子は`.bin`や`.hex`などを使うことが多いです。3つ目の引数である`err => {}`はエラー処理で何もしないことを指しています。 + +では、これを`bytebeat.js`として、ターミナルで実行しましょう。 +この時、ffplayでの`-ar`オプションはソースコード内で指定したサンプリングレートと一致させることを忘れないようにしましょう。 + + +```sh +node bytebeat.js +cat jsbytebeat.hex | ffplay -f u8 -i pipe:0 -ar 8k -ac 1 +``` + +うまくいけば、5秒分の音声が再生されて停止するはずです。 + +ffplayの代わりにffmpegでwavファイルとして改めて出力することもできます。 + +```sh +cat jsbytebeat.hex | ffmpeg -f u8 -ar 8k -i pipe:0 -c:a pcm_u8 -ac 1 -y jsbytebeat.wav +``` + + +### 波形を簡易的に観察してみよう + +試しにbytebeat関数をtをそのまま返すだけの関数としてみます。 + +```js +const bytebeat = t => + t +``` + +この時、tの数値自体は数十万などまで際限なく上昇し続けますが、最終的に`Uint8Array`に書き込まれるときには整数部分下位8bitのみが書き込まれます。どういうことかというと、0~255まで上昇するとまた0に戻るのです。 + +この、0~255を書き込んだ`jsbytebeat.hex`をVSCodeのHex Editorで開くと次のような見た目をしています。 + +![バイナリエディタで0~255までが連続するバイナリデータを表示したVisual Studio Codeのスクリーンショット。](binary.png) + +00からFF(255)まで順番に数値が上昇して、また00に戻っているのがわかります。 + +しかし、バイナリを直接Hex Editorで見るだけではあまりにどんな波形が生成されてるのかわかりにくいです。 + +ffmpegで書き出してAudacityで見たり、ffplayの波形表示モードを使うこともできるのですが、せっかくなので、簡単な方法でデータをプロットしてみることにしましょう。 + +先ほどのbytebeat.jsの後半に以下の行を追加します。 + +```js +let file = fs.createWriteStream("graph.txt"); +for (byte of data){ + let txt = ""; + for (i = 0; i < byte; i++) { + txt += "|"; + } + txt += "\n"; + file.write(txt); +} +file.end(); +``` + +上のコードは、`data`の配列を1バイト分読み取り、データの数値の分だけ文字(|)を書いて、改行し、また次の1バイトを読む……というのを繰り返し、graph.txtというファイルを作っています。 + +これで`node bytebeat.js`を改めて実行すると、ディレクトリに`graph.txt`が作られます。 + +これをVSCodeで開くとこんな感じになるはず。 + +![](graph.png) + +文字数の大きさや、テキストの折り返し設定によってい表示は異なりますが、1行ごとに1文字ずつ増えることでノコギリ状の波形がプロットできています。 + +### 連続して実行できるようにしよう + +`Uint8Array`の中身を標準出力に書き込むの自体は、`process.stdout.write(data)`と割と簡単にできますが、それを永続的に続けられるようにするのは意外と面倒です。 + +とりあえず、先ほど配列生成をしたコードを標準出力に書き出せるように変えましょう。 + +```js + const data = Uint8Array.from({ length: length }, + (v, t) => bytebeat(t) + ); + process.stdout.write(data); +``` + +このファイルを`bytebeat_stream.js`としましょう。 +これでnodeの出力を直接パイプして5秒間は再生できるようになりました。 + +```sh +node bytebeat_stream.js | ffplay -f u8 -i pipe:0 -ar 8k -ac 1 +``` + +最終的にはこれを連続して行えるようにしたいので、こんな感じに無限ループを作ってみます。 + +```js +while(true){ + const data = Uint8Array.from({ length: length }, + (v, t) => bytebeat(t) + ); + process.stdout.write(data); +} +``` + +このコードには2つの問題があります。1つ目に、tは配列生成時に作られるインデックスなので、5秒ごとに0にリセットされてしまいます。そのため、tは外側にグローバルな変数として定義して、更新するようにしましょう。 + +```js +let t = 0; +while(true){ + const data = Uint8Array.from({ length: length }, + (v, _t) => { + const res = bytebeat(t); + t++; + return res; + } + ); + process.stdout.write(data); +} +``` + +`t`は後から書き換える変数として宣言するために`const`ではなく`let`で宣言してください。 + +また元々の配列生成に使っていた引数`(v,t)`はもう使わないので、変数`t`と名前が被らないように`_t`と変えておきましょう。 + +もう1つの問題としては、バイト列を生成する速度が実際にオーディオドライバーで消費されるよりも圧倒的に速いことです。 +(これは元のC言語のプログラムでもそういう仕様なのであまり気にしなくても良いのですが、、、)使われることのないデータが無限に生成されてパイプに流されるとメモリを異常に食ったりするので、5秒分の配列を生成したら5秒分休むようなコードに変えましょう。 +こうしたコードの実現方法はいくつかあるのですが、簡単な方法は特定の関数を一定周期で実行し続ける、`setInterval`関数を使うことです。 + +まず、5秒分標準出力に書き込む部分を`mainProcess`として関数にしましょう。 + +```js +const mainProcess = ()=> { + const data = Uint8Array.from({ length: length }, + (v, _t) => { + const res = bytebeat(t); + t += 1; + return res + } + ); + process.stdout.write(data); +}; +``` +これを、`setInterval`に指定します。第2引数に実行間隔を指定しますが、この時の数値の単位はミリ秒です。なので、`seconds`で指定した秒数を1000で割ってあげましょう。 + +```js +setInterval(mainProcess,seconds / 1000.0); +``` + +実際には、`mainProcess`の実行にも多少なり時間がかかるはずなので、ピッタリ5秒分を生成して5秒待つ、をやっているとオーディオドライバに書き込むデータが不足して落ちるケースがたまにあるようです。そうした場合`1000.0`の代わりに`1010.0`とかにして実行感覚を多少速くしてあげるのもいいでしょう。 + +そういうわけで、完成版`bytebeat_stream.js`は次のような感じで完成です。 + +```js +const sample_rate = 8000; +const seconds = 1; +const length = sample_rate * seconds; +const bytebeat = t => + (((t >> 10 ^ t >> 11) % 5) * t >> 16) * ((t >> 14 & 3 ^ t >> 15 & 1) + 1) * t % 99 + ((3 + (t >> 14 & 3) - (t >> 16 & 1)) / 3 * t % 99 & 64); +let t = 0; + +const mainProcess = () =>{ + const data = Uint8Array.from({ length: length }, + (v, _t) => { + const res = bytebeat(t); + t += 1; + return res + } + ); + process.stdout.write(data); +}; + +setInterval(mainProcess,seconds / 1000.0); +``` + + + +## 補足(備忘録) + +### Javascriptでの整数演算の処理について + +JSで最終的に整数の値をUint8Arrayに詰め込むときの数値型の変換がC言語でのBytebeatと同じになるかどうかは実はそんなに自明ではありません。 + +例えばNode.jsのREPLを開いていくつか計算してみると、 +``` +> 1<<30 +1073741824 +> 1<<31 +-2147483648 +> 1<<32 +1 + +> (1<<31)+0.1 +-2147483647.9 +> 1.1<<31 +-2147483648 +> 0.9<<31 +0 + +> 2 ** 52 +4503599627370496 +> 2**52+1 +4503599627370497 +> 2 ** 53 +9007199254740992 +> 2 ** 53 +1 +9007199254740992 +``` + +といった感じになっています。ここから、仕様を調べずともおおよそ次のことができます。 + +- JSの数値の内部表現は64bit浮動小数点(C言語における`double`)である。 +- うち、仮数部分(指数部が0の場合の整数値)signed 53bitである(上位32bitを抜き出すとCの`int`/`int32_t`になる)。 +- &、ビット演算を行う際は、一旦整数に切り捨てをしてから、signed 32bit同士の演算として計算する。 +- `Uint8Array`などに入れるときは下位ビットを切り出してキャストしている。52bitの整数から32bitにキャストされるときにも下位32ビットが使われている。 + +後々調べたら大体この仕様であっているようです。 + +この挙動が結局、C言語でBytebeatをやる際には`t`は`main`関数の第1引数、つまり`int`を使い、`putchar`をするときに`char`型にキャストされるケースと同じ結果を導くようです。 + +C言語とJavascriptで簡単に同じ音が鳴るのは結構絶妙な仕様のバランスの上に成立しているように見えます。そこまで見越して作っていたのかどうかはよくわかりませんが・・・。 + +ただ、よく考えるとt++で時刻を更新して行ったときに、JavaScriptでは2^52まで足されたあと、0に戻るのではなく精度が落ちたままインクリメントが続くことになりそうです。例えばサンプルレート44.1kHzのモノラルの場合どのくらいから精度が落ちるのでしょうか。 + +```sh +> (2**52 /44100)/(60*60*24*365) +3238.2813460788693 +``` +  +3238年間は心配なさそうです。 + + diff --git a/content/docs/2023/mediaart-programming2/4/binary.png b/content/docs/2023/mediaart-programming2/4/binary.png new file mode 100644 index 0000000..4a0f388 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/binary.png differ diff --git a/content/docs/2023/mediaart-programming2/4/graph.png b/content/docs/2023/mediaart-programming2/4/graph.png new file mode 100644 index 0000000..ccaf3e0 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/graph.png differ diff --git a/content/docs/2023/mediaart-programming2/4/radio1.png b/content/docs/2023/mediaart-programming2/4/radio1.png new file mode 100644 index 0000000..29b54bf Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/radio1.png differ diff --git a/content/docs/2023/mediaart-programming2/4/radio2.png b/content/docs/2023/mediaart-programming2/4/radio2.png new file mode 100644 index 0000000..69b2112 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/radio2.png differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.001.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.001.jpeg new file mode 100644 index 0000000..094612b Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.001.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.002.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.002.jpeg new file mode 100644 index 0000000..e520721 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.002.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.003.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.003.jpeg new file mode 100644 index 0000000..b6ef9a5 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.003.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.004.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.004.jpeg new file mode 100644 index 0000000..28eab87 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.004.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.005.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.005.jpeg new file mode 100644 index 0000000..c42430b Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.005.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.006.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.006.jpeg new file mode 100644 index 0000000..cc41f9c Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.006.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.007.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.007.jpeg new file mode 100644 index 0000000..548932a Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.007.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.008.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.008.jpeg new file mode 100644 index 0000000..86e2f78 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.008.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.009.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.009.jpeg new file mode 100644 index 0000000..36b7ccc Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.009.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.010.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.010.jpeg new file mode 100644 index 0000000..ec8c132 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.010.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.011.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.011.jpeg new file mode 100644 index 0000000..7bae828 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.011.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.012.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.012.jpeg new file mode 100644 index 0000000..3d76129 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.012.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.013.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.013.jpeg new file mode 100644 index 0000000..0d48035 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.013.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.014.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.014.jpeg new file mode 100644 index 0000000..a3a0536 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.014.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.015.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.015.jpeg new file mode 100644 index 0000000..e4c6141 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.015.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.016.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.016.jpeg new file mode 100644 index 0000000..19aeb5c Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.016.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.017.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.017.jpeg new file mode 100644 index 0000000..1746fd7 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.017.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.018.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.018.jpeg new file mode 100644 index 0000000..27004d2 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.018.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.019.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.019.jpeg new file mode 100644 index 0000000..f707a74 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.019.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.020.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.020.jpeg new file mode 100644 index 0000000..6db6875 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.020.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.021.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.021.jpeg new file mode 100644 index 0000000..8ac4866 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.021.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.022.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.022.jpeg new file mode 100644 index 0000000..9a64dac Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.022.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.023.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.023.jpeg new file mode 100644 index 0000000..49e39b0 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.023.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.024.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.024.jpeg new file mode 100644 index 0000000..4148940 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.024.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.025.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.025.jpeg new file mode 100644 index 0000000..8c13cf4 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.025.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.026.jpeg b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.026.jpeg new file mode 100644 index 0000000..46e81c7 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/4/slides/2023-media-art-programming2-4.026.jpeg differ diff --git a/content/docs/2023/mediaart-programming2/4/slides/index.en.md b/content/docs/2023/mediaart-programming2/4/slides/index.en.md new file mode 100644 index 0000000..d0f9633 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/4/slides/index.en.md @@ -0,0 +1,10 @@ +--- +title: "Media Art Programming 2 2023 Week 4 Slides" +date: 2023-10-27T16:40:01+09:00 +bookHidden: true +--- + + +# Slides + +{{< slides_jpg >}} \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/4/slides/index.md b/content/docs/2023/mediaart-programming2/4/slides/index.md new file mode 100644 index 0000000..162dfac --- /dev/null +++ b/content/docs/2023/mediaart-programming2/4/slides/index.md @@ -0,0 +1,10 @@ +--- +title: "メディアアート・プログラミング2 2023年 第4回 スライド" +date: 2023-10-27T16:40:01+09:00 +bookHidden: true +--- + + +# スライド + +{{< slides_jpg >}} \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/5/2023-media-art-programming2-5.pdf b/content/docs/2023/mediaart-programming2/5/2023-media-art-programming2-5.pdf new file mode 100644 index 0000000..6ca48d2 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/5/2023-media-art-programming2-5.pdf differ diff --git a/content/docs/2023/mediaart-programming2/5/_index.en.md b/content/docs/2023/mediaart-programming2/5/_index.en.md new file mode 100644 index 0000000..74cf6b5 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/5/_index.en.md @@ -0,0 +1,15 @@ +--- +title: Week 5 +date: 2023-10-31 +weight: 5 +draft: false +params: + pdf_path: 2023-media-art-programming2-5.pdf +--- + +# 2023 Media Art Programming #5 + +## Slides + +{{< embed_pdf >}} + diff --git a/content/docs/2023/mediaart-programming2/5/_index.md b/content/docs/2023/mediaart-programming2/5/_index.md new file mode 100644 index 0000000..148e223 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/5/_index.md @@ -0,0 +1,139 @@ +--- +title: 第5週 +date: 2023-10-31 +weight: 5 +draft: false +params: + pdf_path: 2023-media-art-programming2-5.pdf +--- + +# 2023年 メディアアート・プログラミング 第5回 + +## スライド + +{{< embed_pdf >}} + +## テキスト操作のサンプルコード + +### load_text.js(ファイルの読み込み) + +```js +//ファイル読み込みライブラリを使用 +const fs = require("fs"); +//ファイル名の指定(./はこのjsファイルと同階層にあることを明示) +const src = "./henshin.txt"; +//ファイルを読み込み +const bytes = fs.readFileSync(src); +//バイト列から文字列に +const txt = bytes.toString(); +console.log(txt); +``` + +{{< button href="load_text.js">}}load_text.js{{< /button >}} + +### text_as_array.js (文字列から文字をインデックスで取り出す) + +文字列オブジェクトはJavascriptの中では配列のように`str[idx]`として先頭から`idx`番目の文字を取り出せます。 + +```js +///...以上load_text.jsと同じ +//配列として先頭から100文字コンソールに表示 +for (let i =0;i<100;i++) { + console.log(txt[i]) +} +``` + +{{< button href="text_as_array.js">}}text_as_array.js{{< /button >}} + +### text_as_array2.js (文字列を文字の配列オブジェクトにする) + +より明確に1文字ずつを要素とした配列オブジェクトにすることもできます。 + +こちらのやり方だと、配列を変換する`map`や`filter`、`reduce`などの便利な関数が使えます。 + +```js +///...以上load_text.jsと同じ +//文字の配列にする +const arr = Array.from(txt); +console.log(arr); +``` + +{{< button href="text_as_array2.js">}}text_as_array2.js{{< /button >}} + +### text_sort.js (文字列を文字コード順でソート) + +```js +///...以上load_text.jsと同じ +//文字の配列にする +const arr = Array.from(txt); +//配列を文字コード順でソート +const sorted = arr.sort(); +//ソートした配列を(区切り文字なしで)結合 +const sorted_str = sorted.join(""); +//ファイルに保存 +fs.writeFileSync("henshin_sorted.txt",sorted_str); +``` +{{< button href="text_sort.js">}}text_sort.js{{< /button >}} + +### text_reversed.js (文字列を前後逆転) + +```js +///...以上load_text.jsと同じ +//文字の配列にする +const arr = Array.from(txt); +//配列を反転 +const reversed = arr.reverse(); +//反転した配列を(区切り文字なしで)結合 +const reversed_str = reversed.join(""); +//ファイルに保存 +fs.writeFileSync("henshin_reversed.txt",reversed_str); +``` + +{{< button href="text_reversed.js">}}text_reversed.js{{< /button >}} + +### text_unicode_shift.js (文字列のUnicodeコードポイントを一つずつずらす) + +```js +///...以上load_text.jsと同じ + +//文字の配列にする +const arr = Array.from(txt); +//配列の文字コードを1つ隣へずらす +const shifted = arr.map( c => String.fromCodePoint(c.codePointAt(0)+1)); +//ソートした配列を(区切り文字なしで)結合 +const shifted_str = shifted.join(""); +//ファイルに保存 +fs.writeFileSync("henshin_shifted.txt",shifted_str); +``` + +{{< button href="text_unicode_shift.js">}}text_unicode_shift.js{{< /button >}} + +### text_unicode_shift_grad.js (文字列のUnicodeコードポイントをずらす確率を段々上げていく) + + +```js +///...以上load_text.jsと同じ + +//文字の配列にする +const arr = Array.from(txt); + +//文字コードをずらす確率 +let probability = 0.0; +const shifted = arr.map(c => { + //配列の最初:0%-最後:100%になるように確率を変更していく + probability += 1 / arr.length; + //randomは0~1の乱数 + if (Math.random() < probability) { + //配列の文字コードを1つ隣へずらす + return String.fromCodePoint(c.codePointAt(0) + 1) + } else { + return c + } +}); +//ソートした配列を(区切り文字なしで)結合 +const shifted_str = shifted.join(""); +//ファイルに保存 +fs.writeFileSync("henshin_shifted_grad.txt", shifted_str); +``` + +{{< button href="text_unicode_shift_grad.js">}}text_unicode_shift_grad.js{{< /button >}} diff --git a/content/docs/2023/mediaart-programming2/5/load_text.js b/content/docs/2023/mediaart-programming2/5/load_text.js new file mode 100644 index 0000000..039c01c --- /dev/null +++ b/content/docs/2023/mediaart-programming2/5/load_text.js @@ -0,0 +1,9 @@ +//ファイル読み込みライブラリを使用 +const fs = require("fs"); +//ファイル名の指定(./はこのjsファイルと同階層にあることを明示) +const src = "./henshin.txt"; +//ファイルを読み込み +const bytes = fs.readFileSync(src); +//バイト列から文字列に +const txt = bytes.toString(); +console.log(txt); \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/5/map2_txt_basic.js b/content/docs/2023/mediaart-programming2/5/map2_txt_basic.js new file mode 100644 index 0000000..76b37f1 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/5/map2_txt_basic.js @@ -0,0 +1,69 @@ +const fs = require("fs"); +//青空文庫から落としたファイルの場合、一度shift-jisからutf-8に変換すること。 +//例で使用したのはフランツ・カフカ「変身」 +//https://www.aozora.gr.jp/cards/001235/card49866.html +const src = "henshin.txt"; +//ファイルをテキストデータとして読み込み +const txt = fs.readFileSync(src).toString(); + +//長いデータの中身を見てみたい場合は、頭の1000文字だけ取り出してコンソールに流すなどする +// const summary = txt.slice(0,1000); +// console.log(summary) + +// 主人公の名前だけを抜き出して空白に置き換える +const no_gregor = txt.replace(/グレゴール/gm, "《 》"); + +fs.writeFileSync("henshin_nogregor.txt", no_gregor); + +let only_gregor = ""; +let lines = txt.split(/\n/); + +//逆に、主人公の名前以外は全て◻︎で置き換えてみよう +for (l of lines) { + const array = l.split("グレゴール"); + if (array.length > 1) { + only_gregor += array.map((s) => "□".repeat(s.length)).join('グレゴール'); + } else { + only_gregor += "□".repeat(array[0].length) + } + only_gregor += "\n" +} +fs.writeFileSync("henshin_onlygregor.txt", only_gregor); + +//会話だけを抜き出してみる +let only_spoken_words = ""; +for (l of lines) { + // let matches= l.match(/「(.*)」/g); + let matches = l.match(/「([^」]+)」/g); + if (matches != null) { + only_spoken_words += matches.join("\n") + "\n" + } +} +fs.writeFileSync("henshin_onlyspokenwords.txt", only_spoken_words); + +//会話の中で!で終わるものだけを抜き出してみる +let excramation = ""; +for (l of lines) { + let matches = l.match(/(?!。| |「)([^。 「]*?)!/g); + if (matches != null) { + excramation += matches.join("\n") + "\n" + } +} + +fs.writeFileSync("henshin_excramation.txt", excramation); + + +//テキストを文字の配列として扱い、後半に行くにつれて文字コードを確率的にずらしていく +let nextunicode = ""; +let probability = 0.0; +const tarray = Array.from(txt); +for (const c of tarray) { + if (c.at(0) == "\n") { + nextunicode += "\n"; + } else { + nextunicode += String.fromCodePoint(c.codePointAt(0) + Math.floor(Math.random() * probability * 6)); + } + probability += 1 / tarray.length; +} + +fs.writeFileSync("henshin_nextunicode.txt", nextunicode); \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/5/text_as_array.js b/content/docs/2023/mediaart-programming2/5/text_as_array.js new file mode 100644 index 0000000..1bbcc31 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/5/text_as_array.js @@ -0,0 +1,12 @@ +//ファイル読み込みライブラリを使用 +const fs = require("fs"); +//ファイル名の指定(./はこのjsファイルと同階層にあることを明示) +const src = "./henshin.txt"; +//ファイルを読み込み +const bytes = fs.readFileSync(src); +//バイト列から文字列に +const txt = bytes.toString(); +//配列として先頭から100文字コンソールに表示 +for (let i =0;i<100;i++) { + console.log(txt[i]) +} \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/5/text_as_array2.js b/content/docs/2023/mediaart-programming2/5/text_as_array2.js new file mode 100644 index 0000000..e3e55ae --- /dev/null +++ b/content/docs/2023/mediaart-programming2/5/text_as_array2.js @@ -0,0 +1,11 @@ +//ファイル読み込みライブラリを使用 +const fs = require("fs"); +//ファイル名の指定(./はこのjsファイルと同階層にあることを明示) +const src = "./henshin.txt"; +//ファイルを読み込み +const bytes = fs.readFileSync(src); +//バイト列から文字列に +const txt = bytes.toString(); +//文字の配列にする +const arr = Array.from(txt); +console.log(arr); \ No newline at end of file diff --git a/content/docs/2023/mediaart-programming2/5/text_reversed.js b/content/docs/2023/mediaart-programming2/5/text_reversed.js new file mode 100644 index 0000000..4af31c3 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/5/text_reversed.js @@ -0,0 +1,16 @@ +//ファイル読み込みライブラリを使用 +const fs = require("fs"); +//ファイル名の指定(./はこのjsファイルと同階層にあることを明示) +const src = "./henshin.txt"; +//ファイルを読み込み +const bytes = fs.readFileSync(src); +//バイト列から文字列に +const txt = bytes.toString(); +//文字の配列にする +const arr = Array.from(txt); +//配列を反転 +const reversed = arr.reverse(); +//反転した配列を(区切り文字なしで)結合 +const reversed_str = reversed.join(""); +//ファイルに保存 +fs.writeFileSync("henshin_reversed.txt",reversed_str); diff --git a/content/docs/2023/mediaart-programming2/5/text_sort.js b/content/docs/2023/mediaart-programming2/5/text_sort.js new file mode 100644 index 0000000..fce907d --- /dev/null +++ b/content/docs/2023/mediaart-programming2/5/text_sort.js @@ -0,0 +1,16 @@ +//ファイル読み込みライブラリを使用 +const fs = require("fs"); +//ファイル名の指定(./はこのjsファイルと同階層にあることを明示) +const src = "./henshin.txt"; +//ファイルを読み込み +const bytes = fs.readFileSync(src); +//バイト列から文字列に +const txt = bytes.toString(); +//文字の配列にする +const arr = Array.from(txt); +//配列を文字コード順でソート +const sorted = arr.sort(); +//ソートした配列を(区切り文字なしで)結合 +const sorted_str = sorted.join(""); +//ファイルに保存 +fs.writeFileSync("henshin_sorted.txt",sorted_str); diff --git a/content/docs/2023/mediaart-programming2/5/text_unicode_shift.js b/content/docs/2023/mediaart-programming2/5/text_unicode_shift.js new file mode 100644 index 0000000..bf03f6b --- /dev/null +++ b/content/docs/2023/mediaart-programming2/5/text_unicode_shift.js @@ -0,0 +1,16 @@ +//ファイル読み込みライブラリを使用 +const fs = require("fs"); +//ファイル名の指定(./はこのjsファイルと同階層にあることを明示) +const src = "./henshin.txt"; +//ファイルを読み込み +const bytes = fs.readFileSync(src); +//バイト列から文字列に +const txt = bytes.toString(); +//文字の配列にする +const arr = Array.from(txt); +//配列の文字コードを1つ隣へずらす +const shifted = arr.map( c => String.fromCodePoint(c.codePointAt(0)+1)); +//ソートした配列を(区切り文字なしで)結合 +const shifted_str = shifted.join(""); +//ファイルに保存 +fs.writeFileSync("henshin_shifted.txt",shifted_str); diff --git a/content/docs/2023/mediaart-programming2/5/text_unicode_shift_grad.js b/content/docs/2023/mediaart-programming2/5/text_unicode_shift_grad.js new file mode 100644 index 0000000..537805b --- /dev/null +++ b/content/docs/2023/mediaart-programming2/5/text_unicode_shift_grad.js @@ -0,0 +1,28 @@ +//ファイル読み込みライブラリを使用 +const fs = require("fs"); +//ファイル名の指定(./はこのjsファイルと同階層にあることを明示) +const src = "./henshin.txt"; +//ファイルを読み込み +const bytes = fs.readFileSync(src); +//バイト列から文字列に +const txt = bytes.toString(); +//文字の配列にする +const arr = Array.from(txt); + +//文字コードをずらす確率 +let probability = 0.0; +const shifted = arr.map(c => { + //配列の最初:0%-最後:100%になるように確率を変更していく + probability += 1 / arr.length; + //randomは0~1の乱数 + if (Math.random() < probability) { + //配列の文字コードを1つ隣へずらす + return String.fromCodePoint(c.codePointAt(0) + 1) + } else { + return c + } +}); +//ソートした配列を(区切り文字なしで)結合 +const shifted_str = shifted.join(""); +//ファイルに保存 +fs.writeFileSync("henshin_shifted_grad.txt", shifted_str); diff --git a/content/docs/2023/mediaart-programming2/6/2023-media-art-programming2-6.pdf b/content/docs/2023/mediaart-programming2/6/2023-media-art-programming2-6.pdf new file mode 100644 index 0000000..1da92ae Binary files /dev/null and b/content/docs/2023/mediaart-programming2/6/2023-media-art-programming2-6.pdf differ diff --git a/content/docs/2023/mediaart-programming2/6/_index.en.md b/content/docs/2023/mediaart-programming2/6/_index.en.md new file mode 100644 index 0000000..a1b2660 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/6/_index.en.md @@ -0,0 +1,15 @@ +--- +title: Week 6 +date: 2023-11-10 +weight: 6 +draft: false +params: + pdf_path: 2023-media-art-programming2-6.pdf +--- + +# 2023 Media Art Programming #6 + +## Slides + +{{< embed_pdf >}} + diff --git a/content/docs/2023/mediaart-programming2/6/_index.md b/content/docs/2023/mediaart-programming2/6/_index.md new file mode 100644 index 0000000..90d3047 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/6/_index.md @@ -0,0 +1,14 @@ +--- +title: 第6週 +date: 2023-11-10 +weight: 6 +draft: false +params: + pdf_path: 2023-media-art-programming2-6.pdf +--- + +# 2023年 メディアアート・プログラミング 第6回 + +## スライド + +{{< embed_pdf >}} diff --git a/content/docs/2023/mediaart-programming2/7/2023-media-art-programming2-7.pdf b/content/docs/2023/mediaart-programming2/7/2023-media-art-programming2-7.pdf new file mode 100644 index 0000000..aa8543f Binary files /dev/null and b/content/docs/2023/mediaart-programming2/7/2023-media-art-programming2-7.pdf differ diff --git a/content/docs/2023/mediaart-programming2/7/_index.en.md b/content/docs/2023/mediaart-programming2/7/_index.en.md new file mode 100644 index 0000000..235cfb2 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/7/_index.en.md @@ -0,0 +1,15 @@ +--- +title: Week 7 +date: 2023-11-17 +weight: 7 +draft: false +params: + pdf_path: 2023-media-art-programming2-7.pdf +--- + +# 2023 Media Art Programming #8 + +## Slides + +{{< embed_pdf >}} + diff --git a/content/docs/2023/mediaart-programming2/7/_index.md b/content/docs/2023/mediaart-programming2/7/_index.md new file mode 100644 index 0000000..8b78cf1 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/7/_index.md @@ -0,0 +1,14 @@ +--- +title: 第7週 +date: 2023-11-17 +weight: 7 +draft: false +params: + pdf_path: 2023-media-art-programming2-7.pdf +--- + +# 2023年 メディアアート・プログラミング 第7回 + +## スライド + +{{< embed_pdf >}} diff --git a/content/docs/2023/mediaart-programming2/8/2023-media-art-programming2-8.pdf b/content/docs/2023/mediaart-programming2/8/2023-media-art-programming2-8.pdf new file mode 100644 index 0000000..73909d8 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/8/2023-media-art-programming2-8.pdf differ diff --git a/content/docs/2023/mediaart-programming2/8/_index.en.md b/content/docs/2023/mediaart-programming2/8/_index.en.md new file mode 100644 index 0000000..b95effc --- /dev/null +++ b/content/docs/2023/mediaart-programming2/8/_index.en.md @@ -0,0 +1,15 @@ +--- +title: Week 8 +date: 2023-11-24 +weight: 8 +draft: false +params: + pdf_path: 2023-media-art-programming2-8.pdf +--- + +# 2023 Media Art Programming #8 + +## Slides + +{{< embed_pdf >}} + diff --git a/content/docs/2023/mediaart-programming2/8/_index.md b/content/docs/2023/mediaart-programming2/8/_index.md new file mode 100644 index 0000000..310c518 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/8/_index.md @@ -0,0 +1,14 @@ +--- +title: 第8週 +date: 2023-11-24 +weight: 8 +draft: false +params: + pdf_path: 2023-media-art-programming2-8.pdf +--- + +# 2023年 メディアアート・プログラミング 第8回 + +## スライド + +{{< embed_pdf >}} diff --git a/content/docs/2023/mediaart-programming2/9/2023-media-art-programming2-9.pdf b/content/docs/2023/mediaart-programming2/9/2023-media-art-programming2-9.pdf new file mode 100644 index 0000000..9dc78e0 Binary files /dev/null and b/content/docs/2023/mediaart-programming2/9/2023-media-art-programming2-9.pdf differ diff --git a/content/docs/2023/mediaart-programming2/9/_index.en.md b/content/docs/2023/mediaart-programming2/9/_index.en.md new file mode 100644 index 0000000..ffbc880 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/9/_index.en.md @@ -0,0 +1,15 @@ +--- +title: Week 9 +date: 2023-12-01 +weight: 9 +draft: false +params: + pdf_path: 2023-media-art-programming2-9.pdf +--- + +# 2023 Media Art Programming #9 + +## Slides + +{{< embed_pdf >}} + diff --git a/content/docs/2023/mediaart-programming2/9/_index.md b/content/docs/2023/mediaart-programming2/9/_index.md new file mode 100644 index 0000000..d8f2a32 --- /dev/null +++ b/content/docs/2023/mediaart-programming2/9/_index.md @@ -0,0 +1,14 @@ +--- +title: 第9週 +date: 2023-12-01 +weight: 9 +draft: false +params: + pdf_path: 2023-media-art-programming2-9.pdf +--- + +# 2023年 メディアアート・プログラミング 第9回 + +## スライド + +{{< embed_pdf >}} diff --git a/content/docs/2023/mediaart-programming2/_index.en.md b/content/docs/2023/mediaart-programming2/_index.en.md index a4123d2..280f6e8 100644 --- a/content/docs/2023/mediaart-programming2/_index.en.md +++ b/content/docs/2023/mediaart-programming2/_index.en.md @@ -1,6 +1,6 @@ --- title: 2023 Tokyo University of the Arts Art media Center 「Media Art Programming II」(Fall-Winter Friday 4) -weight: 1 +weight: 2 bookCollapseSection: true --- diff --git a/content/docs/2023/mediaart-programming2/_index.md b/content/docs/2023/mediaart-programming2/_index.md index fbfdc83..95b7801 100644 --- a/content/docs/2023/mediaart-programming2/_index.md +++ b/content/docs/2023/mediaart-programming2/_index.md @@ -1,6 +1,6 @@ --- title: 2023年 東京藝術大学 芸術情報センター開設科目 「メディアアート・プログラミングII」(後期 金曜4限) -weight: 1 +weight: 2 bookCollapseSection: true --- # 2023年 東京藝術大学 芸術情報センター開設科目 「メディアアート・プログラミングII」 @@ -14,11 +14,11 @@ bookCollapseSection: true ## 授業概要 本授業では、プログラミングを手段に用いるさまざまな実践を通して、テクノロジーを批評的視座で捉える表現のための基礎知識を身につけることを目指す。メディアアートと呼ばれることのある表現の中でも、映像や音楽をコンピューターで作るものではなく、プログラミングやコンピューターを使うことそれ自体が表現の問いやテーマであるものを中心に扱う。全15回の授業中で大きく次の3つのテーマを扱う。 + 1. 詩とコンピューティング 2. 再帰とプログラミング言語 3. インターネットと公共財 - ## 到達目標・カリキュラム上の位置付け 本授業の到達目標は、履修者がプログラミングを中心とした実践を通して、コンピューターという情報機器の仕組みについてより高度に理解し、自らの制作の手段として導入できるようになることである。 @@ -29,31 +29,33 @@ bookCollapseSection: true 内容は進行状況に応じて変更になる可能性があります。 -1. (10/6). オリエンテーション -2. (10/13). ターミナルを扱ってみる/10 Print -3. (10/20). テキストから作る音:Bytebeat -4. (10/27). グリッチ入門:画像と音の相互変換 -5. (10/31 水曜振替). コンピューターに詩を書かせる -6. (11/7). 難解プログラミング言語と芸術 -7. (11/14). 二次元のプログラム(Befunge) -8. (11/24). プログラミング言語自体を作る.1 -9. (12/1) プログラミング言語自体を作る.2 -10. (12/8). インターネットと公共財.1 (HTMLとWeb) -11. (12/15). インターネットと公共財.2 (スクレイピング) -12. (12/22). ゲスト講義 -13. (1/5). 課題制作.1 -14. (1/12). 課題製作.2 -15. (1/26). 課題発表、講評、まとめ +(大学公式のシラバスから一部更新されています)。 + +1. [(10/6) オリエンテーション](./1) +2. [(10/13) ターミナルを扱ってみる/10 Print](./2) +3. [(10/20) グリッチ入門:画像と音の相互変換](./3) +4. [(10/27) テキストから作る音:Bytebeat](./4) +5. [(10/31 火曜振替) 配列としてのテキストデータ](./5) +6. [(11/7)Node.jsでのライブラリ利用/単語レベルでのテキスト操作](./6) +7. [(11/14)実行可能なテキスト:L-Systemとプログラミング言語1](./7) +8. [(11/24)実行可能なテキスト:L-Systemとプログラミング言語2/難解プログラミング言語と芸術](./8) +9. [(12/1) インターネットと公共財1/HTMLとスクリーンショット詐欺](./9) +10. [(12/8)インターネットと公共財2/スクレイピングによる表現](./10) +11. [(12/15)インターネットと公共財3/スクレイピングによる表現2](./11) +12. (12/22)課題制作相談会 +13. (1/5) 課題制作.1 +14. (1/19)課題製作.2 (1/12は休講です) +15. (1/26).課題発表、講評、まとめ ## テキスト・参考文献 -「Code as Creative Medium 創造的なプログラミング教育のための実践ガイドブック」(2022) ゴラン・レヴィン 、 テガ・ブレイン著 澤村正樹 、 杉本達應 、 米田研一 訳、BNN -「遙かなる他者のためのデザイン 久保田晃弘の思索と実装」(2017) 久保田 晃弘、BNN +- 「Code as Creative Medium 創造的なプログラミング教育のための実践ガイドブック」(2022) ゴラン・レヴィン 、 テガ・ブレイン著 澤村正樹 、 杉本達應 、 米田研一 訳、BNN +- 「遙かなる他者のためのデザイン 久保田晃弘の思索と実装」(2017) 久保田 晃弘、BNN 英語の参考文献: -"Cracked Media - The Sound of Malfunction" (2009) by Caleb Kelly, MIT Press +- "Cracked Media - The Sound of Malfunction" (2009) by Caleb Kelly, MIT Press ## 準備学習内容・時間の目安 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c40d119 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,158 @@ +{ + "name": "teach-matsuuratomoya-com", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "teach-matsuuratomoya-com", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "deepl-node": "^1.11.0" + } + }, + "node_modules/@types/node": { + "version": "20.10.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", + "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deepl-node": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/deepl-node/-/deepl-node-1.11.0.tgz", + "integrity": "sha512-PLz38WIfWzVScbz4S+32vI9yCUAXy3cpkKSMPC+IDpvrwKrQ2TSzwkoBh7CJOkPjaX8ZMvjwAc+C5eTCPamQTg==", + "dependencies": { + "@types/node": ">=12.0", + "axios": ">=0.21.2 <1.2.0 || >=1.2.2", + "form-data": "^3.0.0", + "loglevel": ">=1.6.2" + }, + "engines": { + "node": ">=12.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/loglevel": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz", + "integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..0d139d4 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "teach-matsuuratomoya-com", + "version": "1.0.0", + "description": "[![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/)", + "main": "translate.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "deepl-node": "^1.11.0" + } +} diff --git a/translate.js b/translate.js new file mode 100644 index 0000000..39b2eb4 --- /dev/null +++ b/translate.js @@ -0,0 +1,68 @@ +const fs = require("fs").promises; +const path = require("path"); +const API_KEY = process.env.DEEPL_API_KEY; +const deepl = require('deepl-node'); +const translator = new deepl.Translator(API_KEY); + + +const main = async () => { + try { + if (!process.argv[2]) { + throw new Error("File path is not set.") + } + const file_path = process.argv[2]; + const writepath = path.dirname(file_path) + '/' + path.parse(file_path).name + ".en" + path.extname(file_path); + console.log(`source: ${file_path}\ndst: ${String(writepath)}`) + console.log(`API_KEY:${API_KEY}`) + const data = await fs.readFile(file_path, 'utf8'); + let chunk = []; + const last = data.split('\n').reduce((acc, line) => { + if (acc && acc.length > 5000) { + chunk.push(acc); + acc = ""; + return line + } else { + return acc + "\n" + line + } + }, ""); + chunk.push(last); + if (chunk[0]) { + const res = await Promise.all(chunk.map(c => { + console.debug(c); + return deeplTranslate(c) + } + )) + const resstr = fixWrongFormatting(res.join("\n")); + await fs.writeFile(writepath, resstr) + } + } catch (error) { + console.error(error) + } +} +async function deeplTranslate(deeplInput) { + return translator + .translateText(deeplInput, "ja", 'en-us') + .then((result) => { + return result.text + }) +} +function fixWrongFormatting(src) { + let res = ""; + //fix codeblock + res = src.replace(/You can use the ``sh/g, "```sh"); + res = res.replace(/`{2}sh\n/g, "```sh\n"); + + res = res.replace(/^.*``([a-z]*)\n/g, "```$1\n"); + res = res.replace(/`{4,}/g, "```"); + //fix inline code + res = res.replace(/`{2}(.+)`{2}/g, "`$1`"); + //fix image link + res = res.replace(/![\t\s]+\[/g, "!["); + //fix link + + res = res.replace(/\][\t\s]+\(/g, "]("); + //fix hugo shortcode + res = res.replace(/>\}{2,}/g, ">}}"); + return res +} +main(); \ No newline at end of file