ååããµã€ã³æ³¢ãå©çšããŠé³æ¥œãã¡ã€ã«ãçæããããã°ã©ã ãäœããŸãããååã®ããã°ã©ã ã§ã¯ãé³éãçªå·ã§æå®ããªããŠã¯ãªãããæ²ããŒã¿ãå ¥åã倧å€ã§ãããããã§ãååã®ããã°ã©ã ã«ãã©ãŠã¶ãã䜿ããUIãã€ããŠèª°ã§ã䜿ãããªã«ãŽãŒã«ãäœã£ãŠã¿ãŸãããã
ãªã«ãŽãŒã«ã®ä»çµã¿
ä»åäœæããã®ã¯ããã©ãŠã¶ã§æ²ããŒã¿ã®å ¥åãã§ãããããªãªã«ãŽãŒã«ã§ãããã©ãŠã¶ã®ç»é¢ã§ãªã«ãŽãŒã«ã®ãã³ãæå®ããããšã§ãæè»œã«æ²ããŒã¿ãäœæã§ããããã«ããŸãã
倧ããªä»çµã¿ãšããŠã¯ãGoèšèªã§Webã¢ããªãäœæããŸããã¢ããªã®ä»çµã¿ãå³ã«ãããšã以äžã®ããã«ãªããŸãã
詳ããèŠãŠã¿ãŸãããããŸããGoèšèªã§HTTPãµãŒããŒãèµ·åããŸãããã©ãŠã¶ã§ãµãŒããŒã«ã¢ã¯ã»ã¹ãããšããªã«ãŽãŒã«ã®ç»é¢HTMLãè¿ä¿¡ããŸãããããŠããŠãŒã¶ãŒã¯ãã©ãŠã¶äžã§ãªã«ãŽãŒã«ã®æ²ããŒã¿ãå ¥åããŸãããããŠãåçãã¿ã³ãæŒããšãAjaxã§æ²ããŒã¿ããµãŒããŒã«éä¿¡ããGoã®ãµãŒããŒåŽã§WAVãã¡ã€ã«ãçæããŸããWAVãã¡ã€ã«ãçæããããããã©ãŠã¶åŽã§WAVãã¡ã€ã«ãèªã¿èŸŒãã§åçããŸãã
ãªããWAVãã¡ã€ã«ã®çæéšåã¯ååäœæããããã°ã©ã ããã®ãŸãŸå©çšããŸãããã®ããããã©ãŠã¶äžã§äœæããæ²ããŒã¿ã¯ããã¢ãã®éµç€ãçªå·ã§è¡šããçªå·(ããŒãçªå·)ãã«ã³ãã§åºåã£ãŠæå®ãããã®ãšããŸãããã®æã0çªãæå®ãããšäŒç¬Šãæå®ãããã®ãšã¿ãªããŸãã
äŸãã°ãããã¬ããŒãã¬ããœããšããããŒã¿ã§ããã°ã60,62,64,0,60,62,64,0ããšããããŒã¿ã«ãªããŸãããªãããã©ãŠã¶ã®éçºè ããŒã«ã§ã³ã³ãœãŒã«ã衚瀺ãããšãã©ããªæ²ããŒã¿ãçæããã®ãã確èªã§ããããã«ããŠããŸãã
ãããžã§ã¯ããäœãã
ããã§ã¯ãååãšåãããã«ãWAVãã¡ã€ã«ãæè»œã«çæããããã«ãgo-wavãšããã©ã€ãã©ãªãã€ã³ã¹ããŒã«ããŸãããããŸãããã©ãŠã¶ã§ãªã«ãŽãŒã«ãåããããã«ãWebãã¬ãŒã ã¯ãŒã¯ã®Ginãã€ã³ã¹ããŒã«ããŸãããã
æåã«ãã³ãã³ãã©ã€ã³ã§ä»¥äžã®ã³ãã³ããå®è¡ããŠãgo-wavãšGinãã€ã³ã¹ããŒã«ããŸãããã
$ go mod init example.com/musicbox
$ go get github.com/youpy/go-wav
$ go get github.com/gin-gonic/gin
ãªããä»åãWAVãã¡ã€ã«ãçæãããµãŒããŒåŽã®Goã®ããã°ã©ã ãmusicbox.goããšããã³ã眮ãHTMLç»é¢ãindex.htmlããšäºã€ã®ãã¡ã€ã«ã§äœããŸãã以äžã®ãããªãã¡ã€ã«æ§æã«ãªãããã«ããŸãããããžã§ã¯ãäžåŒã¯ãã¡ãããããŠã³ããŒãã§ããŸãã
.
âââ go.mod --- Goã®ã¢ãžã¥ãŒã«èšå®ãã¡ã€ã«(èªåçã«äœããã)
âââ musicbox.go --- ãªã«ãŽãŒã«ã®ããã°ã©ã
âââ static
âââ index.html --- ãªã«ãŽãŒã«ã®ç»é¢
âââ box.wav --- WAVãã¡ã€ã«(èªåçã«äœããã)
WAVãã¡ã€ã«çæãµãŒããŒãäœãã
ããã§ã¯ããŸãã¯ãGoèšèªã§WAVãã¡ã€ã«ãçæããHTTPãµãŒããŒããèŠãŠãããŸãããã以äžã®ããã°ã©ã ããmusicbox.goããšããååã§ä¿åããŸãããã
package main
import (
"log"
"math"
"net/http"
"os"
"strconv"
"strings"
"github.com/gin-gonic/gin"
"github.com/youpy/go-wav"
)
const sampleRate = 44100.0 // ãµã³ãã«ã¬ãŒããæå®
const bpm = 120 // ãã³ããæå®
func main() {
// ãµãŒããŒã®èšå®
router := gin.Default()
// ãªã«ãŽãŒã«ã®ç»é¢(HTMLãã¡ã€ã«)ãè¿ã --- (*1)
router.StaticFS("/static", http.Dir("static"))
router.GET("/", func(ctx *gin.Context) {
ctx.Redirect(302, "/static/index.html")
})
// WAVãã¡ã€ã«çæAPI --- (*2)
router.GET("/make", func(ctx *gin.Context) {
notesStr := ctx.Query("notes")
notes := strings.Split(notesStr, ",")
file, _ := os.Create("static/box.wav")
defer file.Close()
len4 := int(sampleRate * 60 / bpm)
sampleSize := uint32(len(notes) * len4)
writer := wav.NewWriter(file, sampleSize, 1, uint32(sampleRate), 16)
for i := 0; i < len(notes); i++ {
// åé³ç¬Šãæžã蟌ã
no, _ := strconv.Atoi(notes[i])
addNote(writer, no, len4)
}
ctx.String(200, "ok")
})
// ãµãŒããŒãèµ·å --- (*3)
err := router.Run("127.0.0.1:8888")
if err != nil {
log.Fatal("ãµãŒããŒèµ·åã«å€±æ", err)
}
}
// é³ç¬Šãæžã蟌ã --- (*4)
func addNote(writer *wav.Writer, note int, length int) {
// é³éããåšæ³¢æ°ãèšç®
tone := 440.0 * math.Pow(2.0, float64(note-69)/12.0)
// ãµã€ã³æ³¢ãæžã蟌ã
samples := make([]wav.Sample, length)
for i := 0; i < length; i++ {
v := math.Sin((float64(i) / float64(sampleRate)) * tone * 2.0 * math.Pi)
v *= 0.3 // é³éãäžãã
// ããããšåãããã€ãºã軜æž
decLen := length / 8 // é³ç¬Šã®æåŸã®é³éãäžãã
if i > length-decLen {
v *= float64((length - i)) / float64(decLen)
}
samples[i].Values[0] = int(v * 0x7FFF)
}
writer.WriteSamples(samples)
}
ç°¡åã«ããã°ã©ã ã®èª¬æãããŸãã(ïŒ1)ã®éšåã§ã¯ããªã«ãŽãŒã«ã®ç»é¢(HTML)ã衚瀺ãããããã«ãªãã€ã¬ã¯ããèšå®ããŸãããŸããstaticãã£ã¬ã¯ããªä»¥äžã«é 眮ãããã¡ã€ã«ã«èªç±ã«ã¢ã¯ã»ã¹ã§ããããã«ããŸãã
(ïŒ2)ã§ã¯ã/makeããšããURLã«ã¢ã¯ã»ã¹ããæãWAVãã¡ã€ã«ãçæãããããã«ããŸããURLåŒæ°ã®notesã«æå®ããæ²ããŒã¿ãååŸãããã®æ²ããŒã¿ã«æ²¿ã£ãŠWAVãã¡ã€ã«ãçæããŸããçæãå®äºããããokãšã ãçãã¬ã¹ãã³ã¹ãè¿ããŸãã
(ïŒ3)ã§ã¯ãµãŒããŒãèµ·åããŸããããã§ã¯ãããŒã8888ã§HTTPãµãŒããŒãèµ·åããŸããWebãã¬ãŒã ã¯ãŒã¯ã®Ginãå©çšããŠãããããéåžžã«ç°¡æœã«åçš®åŠçãèšè¿°ã§ããŸããããªããGinã«é¢ããŠã¯ãæ¬é£èŒã®17åç®ã§è©³ãã解説ããŠããã®ã§åèã«ããŠãã ããã
ãªã«ãŽãŒã«ç»é¢ãäœãã
ç¶ããŠããªã«ãŽãŒã«ç»é¢ãäœæããŸããããstaticãšãããã©ã«ããäœæãã以äžã®HTMLããindex.htmlããšããååã§ä¿åããŸãããªã«ãŽãŒã«ã®ãã³ã¯ãHTMLã®ã©ãžãªããã¯ã¹ããã®ãŸãŸå©çšããŠããŸãã
<html><meta charset="utf-8">
<body>
<h1>ãªã«ãŽãŒã«<button onclick="play()">åç</button></h1>
<div id="box"></div>
</body>
<script>
const MAX_ROWS = 32
// ãªã«ãŽãŒã«ç»é¢ãäœæ(ã©ãžãªããã¯ã¹ãããããäœæ) --- (*1)
const box = document.getElementById('box')
const colors = [0,1,0,1,0,0,1,0,1,0,1,0]
let html = ''
for (let row = 0; row < MAX_ROWS; row++) {
let cols = ''
for (let col = 0; col < 24; col++) {
let bg = (colors[col % 12]) ? 'background-color:#CCC;' : ''
switch (row % 8) {
case 3: bg += `border-bottom:2px solid silver;`; break;
case 7: bg += `border-bottom:2px solid gray;`; break;
}
const va = 60 + col
cols += `<td style="${bg}border-left:1px solid #999;">`
cols += `<input type="radio" id="g${row}" name="g${row}" value="${va}">`
cols += `</td>`
}
html += `<tr>${cols}</tr>`
}
box.innerHTML = `<form id="boxform"><table>${html}</table></form>`
// åçãã¿ã³ãæŒããæã®åŠç
function play() {
// ãªã«ãŽãŒã«ããŒã¿ãäœæ --- (*2)
const res = []
const form = document.getElementById('boxform')
for (let i = 0; i < MAX_ROWS; i++) {
let v = form[`g${i}`].value
if (!v) v = 0
res.push(v)
}
const s = res.join(',').replace(/(,0)+$/, '')
console.log('notes=', s)
// ãµãŒããŒã«éä¿¡ --- (*3)
fetch('/make?notes=' + s).then(r => r.text()).then((text) => {
console.log('response=', text)
const audio = new Audio('/static/box.wav?r=' + s)
audio.currentTime = 0
audio.play()
})
}
</script>
</html>
ç°¡åã«HTML/JavaScriptã«ã€ããŠç޹ä»ããŸãããªã«ãŽãŒã«ã®ãã³ã¯ã©ãžãªããã¯ã¹ããããã衚瀺ããŠå®çŸããŠããŸããã(ïŒ1)ã®éšåã§HTMLãJavaScriptã«ãã£ãŠåçã«çæããŠããŸãã
ãããŠãåçãã¿ã³ãæŒããæã(ïŒ2)ã©ãžãªããã¯ã¹ãããã³ã®åºãããéšåã®æ²ããŒã¿ãåãåºããŸããããããã(ïŒ3)ã§fetch APIãå©çšããŠãµãŒããŒã«æ²ããŒã¿ãéä¿¡ããŸããã¬ã¹ãã³ã¹ãè¿ã£ãŠããããWAVãã¡ã€ã«ãåçããããã«ããŸãã
ãªã«ãŽãŒã«ãå®è¡ããã
ããã§ã¯ãããã°ã©ã ãå®è¡ããŠã¿ãŸããããããã°ã©ã ãå®è¡ããã«ã¯ãã³ãã³ãã©ã€ã³ã§ä»¥äžã®ã³ãã³ããå®è¡ããŸãã
$ go run .
ãããšãHTTPãµãŒããŒãèµ·åããã®ã§ããã©ãŠã¶ã§ãhttp://localhost:8888ãã«ã¢ã¯ã»ã¹ããŸãããããšãªã«ãŽãŒã«ã®ç»é¢ã衚瀺ãããŸããæšªæ¹åãé³çšã§ã瞊æ¹åãæéãšãªã£ãŠããŸããé³çšã¯å·ŠãããããïŒã¬ã¬ïŒããã¡ãœã»ã»ã»ãšãã¢ãã®éµç€ã®ããã«äžŠãã§ããŸãããã³ãåºãããç»é¢äžéšã®ãåçããã¿ã³ãæŒããŸãããããšãWAVãã¡ã€ã«ãçæããã鳿¥œãåçãããŸãã
ãŸãšã
以äžãä»åã¯ãªã«ãŽãŒã«ã®ããã°ã©ã ãäœã£ãŠã¿ãŸãããç¹ã«ãååäœæããWAVãã¡ã€ã«ã®çæããã°ã©ã ãã¡ãã£ãšæ¹è¯ããŠãHTML/JavaScriptã§ç»é¢ãäœã£ãŠã¿ãŸãããGoã®ããã°ã©ã ãšHTMLãã¡ã€ã«ãè¶³ããŠã115è¡ãããããŸãããèŠéããè¯ãã®ã§ããã®æã®ããã°ã©ã ãäœãåèã«ãªãããšã§ãããã
ãã ããå®è¡ããŠã¿ããšåãããŸããããªã«ãŽãŒã«ãšåŒã¶ã«ã¯ããŸãã«ãåçãããé³ãçŽ æŽã§ããããWAVãã¡ã€ã«ãçæããåŠçãæ¹è¯ããŠãããè¯ãé³ã鳎ãããã«ããããæ¹è¯ããŠã¿ããšè¯ãã§ããããå®éã«é³ã鳎ã鳿¥œããã°ã©ãã³ã°ã¯é¢çœãã®ã§ããã²ææŠããŠã¿ãŠãã ããã
èªç±åããã°ã©ããŒããããã¯ãã©ã«ãŠãããã°ã©ãã³ã°ã®æ¥œãããäŒããæŽ»åãããŠããã代衚äœã«ãæ¥æ¬èªããã°ã©ãã³ã°èšèªããªã§ããã ãããã¹ã鳿¥œããµã¯ã©ããªã©ã2001幎ãªã³ã©ã€ã³ãœãã倧è³å ¥è³ã2004幎床æªèžãŠãŒã¹ ã¹ãŒããŒã¯ãªãšãŒã¿èªå®ã2010幎 OSSè²¢ç®è ç« åè³ãæè¡æžãå€ãå·çããŠãããçŽè¿ã§ã¯ããã·ãŽããã¯ãã©ã PythonèªååŠçã®æç§æž(ãã€ããåºç)ããããã«äœ¿ãã!æ¥åã§å®è·µã§ãã! Pythonã«ããAIã»æ©æ¢°åŠç¿ã»æ·±å±€åŠç¿ã¢ããªã®ã€ããæ¹ TensorFlow2察å¿(ãœã·ã )ãããã³ã¬ã§ãã£ããåŠã¶Python(ãã€ããåºç)ããªã©ã



