├── .eslintrc.json ├── .gitattributes ├── .gitignore ├── .modernizrrc.js ├── .travis.yml ├── LICENSE ├── README.md ├── favicon.png ├── index.babel.js ├── index.html ├── lib ├── fontmin-loader.js └── yaml-loader.js ├── ogimage.png ├── package-lock.json ├── package.json ├── songs ├── index.js └── iwashi │ ├── data.yml │ ├── icon.png │ ├── icon_raw.png │ └── score │ ├── base.txt │ ├── bass.txt │ ├── chime1.txt │ ├── chime2.txt │ ├── chord.txt │ ├── chorus1.txt │ ├── chorus2.txt │ ├── chorus3.txt │ ├── chorus4.txt │ ├── chorus5.txt │ ├── chorus6.txt │ ├── clap.txt │ ├── closed-hihat.txt │ ├── cowbell.txt │ ├── cymbal.txt │ ├── snare.txt │ ├── synth1.txt │ └── synth2.txt ├── sound ├── Makefile ├── acchikocchi-sunoko.ogg ├── acchikocchi-sunoko.wav ├── ai-virus.ogg ├── ai-virus.wav ├── aniplex-logo.ogg ├── aniplex-logo.wav ├── aoba-zoi.ogg ├── aoba-zoi.wav ├── atsumori.ogg ├── atsumori.wav ├── badapple-intro.ogg ├── badapple-intro.wav ├── bemybaby-intro.ogg ├── bemybaby-intro.wav ├── chargeman-hai.ogg ├── chargeman-hai.wav ├── cheatbug-rakurai.ogg ├── cheatbug-rakurai.wav ├── chu2koi-au.ogg ├── chu2koi-au.wav ├── chu2koi-stadiometer.ogg ├── chu2koi-stadiometer.wav ├── cookie-marisa.ogg ├── cookie-marisa.wav ├── data.yml ├── deremasu-mashumaro.ogg ├── deremasu-mashumaro.wav ├── deremasu-suimasen.ogg ├── deremasu-suimasen.wav ├── donkeykong-hammer.ogg ├── donkeykong-hammer.wav ├── enta-newwave.ogg ├── enta-newwave.wav ├── evangelion-clap.ogg ├── evangelion-clap.wav ├── evangelion-crack.ogg ├── evangelion-crack.wav ├── fgo-babbage.ogg ├── fgo-babbage.wav ├── fireball-ring.ogg ├── fireball-ring.wav ├── gintama-katsurap.ogg ├── gintama-katsurap.wav ├── gochiusa-tippy-no.ogg ├── gochiusa-tippy-no.wav ├── hitodeman-hea.ogg ├── hitodeman-hea.wav ├── inazuma-pan.ogg ├── inazuma-pan.wav ├── inoubattle-gasstove.ogg ├── inoubattle-gasstove.wav ├── inoubattle-otama.ogg ├── inoubattle-otama.wav ├── ippon-crisp.ogg ├── ippon-crisp.wav ├── jaguarman-waito.ogg ├── jaguarman-waito.wav ├── jajamen-wotagei.ogg ├── jajamen-wotagei.wav ├── jojo-iwashi.ogg ├── jojo-iwashi.wav ├── kabikiller-rah.ogg ├── kabikiller-rah.wav ├── kabuto-ketarosu.ogg ├── kabuto-ketarosu.wav ├── karateka-kick.ogg ├── karateka-kick.wav ├── kemofure-toki.ogg ├── kemofure-toki.wav ├── kemomimi-yononaka.ogg ├── kemomimi-yononaka.wav ├── killme-cymbal.ogg ├── killme-cymbal.wav ├── killme-pyonsuke.ogg ├── killme-pyonsuke.wav ├── kinmoza-clap.ogg ├── kinmoza-clap.wav ├── kokoro-bookoff.ogg ├── kokoro-bookoff.wav ├── legalhigh-anobade.ogg ├── legalhigh-anobade.wav ├── lovelive-shittofire.ogg ├── lovelive-shittofire.wav ├── maguro-drum.ogg ├── maguro-drum.wav ├── matao-crossing.ogg ├── matao-crossing.wav ├── metan-ahoge.ogg ├── metan-ahoge.wav ├── minecraft-blaze.ogg ├── minecraft-blaze.wav ├── minecraft-creeper.ogg ├── minecraft-creeper.wav ├── nanami-jaan.ogg ├── nanami-jaan.wav ├── nichijo-akabeko.ogg ├── nichijo-akabeko.wav ├── nichijo-eh.ogg ├── nichijo-eh.wav ├── nichijo-kokeshi.ogg ├── nichijo-kokeshi.wav ├── nichijo-shake.ogg ├── nichijo-shake.wav ├── nyancat-nya.ogg ├── nyancat-nya.wav ├── nyanyanya-nya.ogg ├── nyanyanya-nya.wav ├── oreo-oh.ogg ├── oreo-oh.wav ├── popute-asahi.ogg ├── popute-asahi.wav ├── prestar-yuupack.ogg ├── prestar-yuupack.wav ├── rizap-cm.ogg ├── rizap-cm.wav ├── sakanakun-akyaa.ogg ├── sakanakun-akyaa.wav ├── saronshippu-ah.ogg ├── saronshippu-ah.wav ├── seirogan-trumpet.ogg ├── seirogan-trumpet.wav ├── shachiku-biku.ogg ├── shachiku-biku.wav ├── shintakarajima-intro.ogg ├── shintakarajima-intro.wav ├── shintakarajima-oh.ogg ├── shintakarajima-oh.wav ├── suntelevision-ossan.ogg ├── suntelevision-ossan.wav ├── tennis-racket.ogg ├── tennis-racket.wav ├── vocal │ └── yufu │ │ ├── 01.ogg │ │ ├── 01.ust │ │ ├── 01.wav │ │ ├── 02.ogg │ │ ├── 02.ust │ │ ├── 02.wav │ │ ├── 03.ogg │ │ ├── 03.ust │ │ ├── 03.wav │ │ ├── 04.ogg │ │ ├── 04.ust │ │ ├── 04.wav │ │ ├── 05.ogg │ │ ├── 05.ust │ │ ├── 05.wav │ │ ├── 06.ogg │ │ ├── 06.ust │ │ ├── 06.wav │ │ ├── 07.ogg │ │ ├── 07.ust │ │ ├── 07.wav │ │ ├── 08.ogg │ │ ├── 08.ust │ │ ├── 08.wav │ │ └── character.png ├── washing-aegi.ogg ├── washing-aegi.wav ├── yukari-cowbell.ogg ├── yukari-cowbell.wav ├── yuyushiki-nantsutte.ogg ├── yuyushiki-nantsutte.wav ├── zen-glass.ogg ├── zen-glass.wav ├── zkai-eh.ogg └── zkai-eh.wav ├── src ├── App.jsx ├── App.pcss ├── Loading.jsx ├── Loading.pcss ├── SoundSelect.jsx ├── SoundSelect.pcss ├── Tooltip.css ├── Tooltip.jsx ├── Track.jsx ├── Track.pcss ├── VocalManager.js ├── VolumeControls.jsx ├── VolumeControls.pcss ├── const.js ├── gist.js ├── params.js └── util.js └── webpack.config.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@hakatashi", 3 | "parserOptions": { 4 | "parser": "babel-eslint" 5 | }, 6 | "rules": { 7 | "camelcase": "off", 8 | "no-console": "off", 9 | "max-len": "off", 10 | "react/no-multi-comp": "off", 11 | "react/forbid-component-props": "off", 12 | "node/no-unsupported-features": "off", 13 | "node/no-unsupported-features/es-syntax": "off", 14 | "node/no-unsupported-features/es-builtins": "off" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | package-lock.json binary 2 | /index.js binary 3 | /index.js.map binary 4 | *.wav filter=lfs diff=lfs merge=lfs -text 5 | *.ogg filter=lfs diff=lfs merge=lfs -text 6 | *.ust filter=lfs diff=lfs merge=lfs -text 7 | *.png filter=lfs diff=lfs merge=lfs -text 8 | favicon.png -filter=lfs -diff=lfs -merge=lfs -text 9 | ogimage.png -filter=lfs -diff=lfs -merge=lfs -text 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | *.reapeaks 61 | *.cache 62 | 63 | /index.js 64 | /index.js.map 65 | -------------------------------------------------------------------------------- /.modernizrrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | minify: true, 3 | options: [ 4 | 'setClasses', 5 | ], 6 | 'feature-detects': [ 7 | 'audio', 8 | 'audio/autoplay', 9 | ], 10 | }; 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - node 4 | dist: trusty 5 | sudo: false 6 | cache: 7 | directories: 8 | - node_modules 9 | before_install: npm install -g greenkeeper-lockfile@1 10 | before_script: greenkeeper-lockfile-update 11 | script: 12 | - npm test 13 | - npm run build 14 | after_script: greenkeeper-lockfile-upload 15 | branches: 16 | except: 17 | - /^v\d+\.\d+\.\d+$/ 18 | - gh-pages 19 | notifications: 20 | webhooks: http://webhook.hakatashi.com/travis 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Koki Takahashi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iwashi 2 | 3 | [![Greenkeeper badge](https://badges.greenkeeper.io/hakatashi/iwashi.svg)](https://greenkeeper.io/) -------------------------------------------------------------------------------- /favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hakatashi/iwashi/ee26e0ff4f3ccca876cf40596f6006738ce9e761/favicon.png -------------------------------------------------------------------------------- /index.babel.js: -------------------------------------------------------------------------------- 1 | require('@babel/polyfill'); 2 | 3 | const React = require('react'); 4 | const ReactDOM = require('react-dom'); 5 | const App = require('./src/App.jsx'); 6 | const gist = require('./src/gist.js'); 7 | const params = require('./src/params.js'); 8 | 9 | require('react-tippy/dist/tippy.css'); 10 | 11 | process.on('unhandledRejection', (error) => { 12 | throw error; 13 | }); 14 | 15 | window.addEventListener('unhandledrejection', (error) => { 16 | throw error; 17 | }); 18 | 19 | (async () => { 20 | const gistData = await (() => { 21 | if (!params.gist || !params.gist.match(/^[\da-f]{20,}$/)) { 22 | return Promise.resolve(null); 23 | } 24 | 25 | return gist.load(params.gist); 26 | })(); 27 | 28 | const reactRoot = document.getElementById('react'); 29 | ReactDOM.render(React.createElement(App, {gistData}), reactRoot); 30 | })(); 31 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | イワシがつちからはえてくるんだ ~原曲不使用音声による音MAD自動演奏~ 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /lib/fontmin-loader.js: -------------------------------------------------------------------------------- 1 | const Fontmin = require('fontmin'); 2 | const loaderUtils = require('loader-utils'); 3 | 4 | module.exports = async function(font) { 5 | const callback = this.async(); 6 | const fontmin = new Fontmin().src(font); 7 | const options = loaderUtils.getOptions(this) || {}; 8 | 9 | if (options.text) { 10 | fontmin.use( 11 | Fontmin.glyph({ 12 | text: options.text, 13 | hinting: false, 14 | }) 15 | ); 16 | } 17 | 18 | fontmin.use(Fontmin.ttf2woff()); 19 | 20 | const fonts = await new Promise((resolve, reject) => { 21 | fontmin.run((error, files) => { 22 | if (error) { 23 | reject(error); 24 | } else { 25 | resolve(files); 26 | } 27 | }); 28 | }); 29 | 30 | const retFont = fonts.find((f) => f.extname === '.woff'); 31 | 32 | callback(null, retFont ? retFont.contents : fonts[0].contents); 33 | }; 34 | 35 | module.exports.raw = true; 36 | -------------------------------------------------------------------------------- /lib/yaml-loader.js: -------------------------------------------------------------------------------- 1 | // So ugly... (;O;) 2 | 3 | const yaml = require('js-yaml'); 4 | 5 | module.exports = (yamlText) => { 6 | const key = Array(100) 7 | .fill() 8 | .map(() => String.fromCodePoint(0x61 + Math.floor(Math.random() * 26))) 9 | .join(''); 10 | 11 | const RequireYamlType = new yaml.Type('!require', { 12 | kind: 'scalar', 13 | construct: (path) => { 14 | const newPath = path || ''; 15 | return `#${key}#${newPath}#${key}#`; 16 | }, 17 | }); 18 | 19 | const YAML_SCHEMA = yaml.Schema.create([RequireYamlType]); 20 | 21 | const data = yaml.load(yamlText, {schema: YAML_SCHEMA}); 22 | const json = JSON.stringify(data); 23 | 24 | return `module.exports = ${json.replace( 25 | new RegExp(`"#${key}#(.+?)#${key}#"`, 'g'), 26 | 'require("$1").default' 27 | )}`; 28 | }; 29 | -------------------------------------------------------------------------------- /ogimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hakatashi/iwashi/ee26e0ff4f3ccca876cf40596f6006738ce9e761/ogimage.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iwashi", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": { 7 | "@babel/core": "^7.4.3", 8 | "@babel/plugin-proposal-class-properties": "^7.4.0", 9 | "@babel/plugin-proposal-object-rest-spread": "^7.4.3", 10 | "@babel/polyfill": "^7.4.3", 11 | "@babel/preset-env": "^7.4.3", 12 | "@babel/preset-react": "^7.0.0", 13 | "@hakatashi/babel-plugin-react-svg": "^2.1.0-1", 14 | "@hakatashi/eslint-config": "^1.8.4", 15 | "autoprefixer": "^9.5.0", 16 | "babel-eslint": "^10.0.1", 17 | "babel-loader": "^8.0.5", 18 | "babel-minify-webpack-plugin": "^0.3.1", 19 | "babel-plugin-react-css-modules": "^5.2.4", 20 | "classnames": "^2.2.6", 21 | "common-tags": "^1.8.0", 22 | "core-js": "^3.0.0", 23 | "css-loader": "^2.1.1", 24 | "cssnano": "^4.1.10", 25 | "eslint": "^5.16.0", 26 | "eslint-plugin-react": "^7.12.4", 27 | "exports-loader": "^0.7.0", 28 | "fontmin": "^0.9.7-beta", 29 | "howler": "^2.1.1", 30 | "husky": "^1.3.1", 31 | "imports-loader": "^0.8.0", 32 | "js-yaml": "^3.13.1", 33 | "lint-staged": "^8.1.5", 34 | "loader-utils": "^2.0.0", 35 | "lodash": "^4.17.11", 36 | "mml-iterator": "^1.1.0", 37 | "modernizr": "github:hakatashi/Modernizr#audio-autoplay", 38 | "modernizr-loader": "^1.0.1", 39 | "napa": "^3.0.0", 40 | "postcss-loader": "^3.0.0", 41 | "precss": "4.0.0", 42 | "preloadjs": "^1.0.1", 43 | "prettier-eslint-cli": "^4.7.1", 44 | "prop-types": "^15.7.2", 45 | "randomcolor": "^0.5.4", 46 | "raw-loader": "^2.0.0", 47 | "react": "^16.8.6", 48 | "react-dom": "^16.8.6", 49 | "react-hammerjs": "^1.0.1", 50 | "react-icons": "^3.5.0", 51 | "react-player": "^2.0.0", 52 | "react-tippy": "^1.2.3", 53 | "style-loader": "^0.23.1", 54 | "url-loader": "^1.1.2", 55 | "webpack": "^4.29.6", 56 | "webpack-cli": "^3.3.0", 57 | "webpack-dev-server": "^3.2.1", 58 | "webpack-sources": "1.3.0" 59 | }, 60 | "devDependencies": {}, 61 | "napa": { 62 | "misaki-font": "http://littlelimit.net/arc/misaki/misaki_ttf_2019-02-03a.zip", 63 | "hatena-icon": "http://hatenacorp.jp/file/hatenaportal/company/Hatena-Bookmark-Logo.zip" 64 | }, 65 | "scripts": { 66 | "install": "napa", 67 | "test": "npm run lint", 68 | "lint": "eslint . --ext .jsx,.js --ignore-path .gitignore", 69 | "format": "prettier-eslint **/*.js **/*.jsx **/*.css **/*.pcss --write", 70 | "build": "webpack --mode production", 71 | "dev": "webpack-dev-server --open" 72 | }, 73 | "husky": { 74 | "hooks": { 75 | "pre-commit": "lint-staged" 76 | } 77 | }, 78 | "lint-staged": { 79 | "*.{js,jsx,css,pcss}": [ 80 | "prettier-eslint --write", 81 | "git add" 82 | ] 83 | }, 84 | "repository": { 85 | "type": "git", 86 | "url": "git+https://github.com/hakatashi/iwashi.git" 87 | }, 88 | "keywords": [], 89 | "author": "Koki Takahashi (http://hakatashi.com/)", 90 | "license": "MIT", 91 | "bugs": { 92 | "url": "https://github.com/hakatashi/iwashi/issues" 93 | }, 94 | "homepage": "https://github.com/hakatashi/iwashi#readme" 95 | } 96 | -------------------------------------------------------------------------------- /songs/index.js: -------------------------------------------------------------------------------- 1 | const mapValues = require('lodash/mapValues'); 2 | const MMLIterator = require('mml-iterator'); 3 | 4 | const iwashi = require('./iwashi/data.yml'); 5 | const {median} = require('../src/util.js'); 6 | 7 | const parseTime = (timeText, resolution) => { 8 | const components = timeText.split('.'); 9 | 10 | if (components.length === 2) { 11 | return ( 12 | (parseInt(components[0]) - 1) * resolution + 13 | ((parseInt(components[1]) - 1) * resolution) / 4 14 | ); 15 | } 16 | 17 | if (components.length === 3) { 18 | const subtime = parseFloat(`${components[1]}.${components[2]}`); 19 | return ( 20 | (parseInt(components[0]) - 1) * resolution + 21 | Math.floor((subtime - 1) * resolution) / 4 22 | ); 23 | } 24 | 25 | throw new Error(`Invalid time: ${timeText}`); 26 | }; 27 | 28 | const compileLyrics = (lyricText, resolution) => { 29 | let currentTime = null; 30 | const lyrics = []; 31 | 32 | for (const line of lyricText.split('\n')) { 33 | if (line.startsWith('=')) { 34 | currentTime = parseTime(line.slice(1), resolution); 35 | if (lyrics.length >= 1 && lyrics[lyrics.length - 1].end === null) { 36 | lyrics[lyrics.length - 1].end = currentTime; 37 | } 38 | } else if (line.trim() !== '') { 39 | lyrics.push({ 40 | text: line.trim(), 41 | start: currentTime, 42 | end: null, 43 | }); 44 | } 45 | } 46 | 47 | return lyrics; 48 | }; 49 | 50 | const compileMml = (text) => { 51 | // Bug of mml-iterator? 52 | const fixedText = text.replace( 53 | /[<>]/g, 54 | (char) => ({'<': '>', '>': '<'}[char]) 55 | ); 56 | 57 | const iterator = new MMLIterator(fixedText); 58 | const notes = Array.from(iterator); 59 | return notes; 60 | }; 61 | 62 | for (const [id, song] of Object.entries({iwashi})) { 63 | module.exports[id] = { 64 | ...song, 65 | length: parseTime(song.length, song.resolution), 66 | lyrics: compileLyrics(song.lyrics, song.resolution), 67 | vocals: mapValues(song.vocals, (vocals) => vocals.map((vocal) => ({ 68 | ...vocal, 69 | start: parseTime(vocal.start, song.resolution), 70 | end: parseTime(vocal.end, song.resolution), 71 | }))), 72 | backgrounds: song.backgrounds.map((background) => ({ 73 | ...background, 74 | time: parseTime(background.time, song.resolution), 75 | })), 76 | tracks: mapValues(song.tracks, (track) => ({ 77 | ...track, 78 | ...(track.score 79 | ? (() => { 80 | const score = compileMml(track.score); 81 | const noteNumbers = score 82 | .map((note) => note.noteNumber) 83 | .filter((note) => note !== undefined); 84 | return { 85 | score, 86 | meanOfNotes: median(noteNumbers), 87 | }; 88 | })() 89 | : {}), 90 | ...(track.start ? {start: parseTime(track.start, song.resolution)} : {}), 91 | ...(track.end ? {end: parseTime(track.end, song.resolution)} : {}), 92 | })), 93 | clearances: song.clearances.map((clearance) => parseTime(clearance, song.resolution)), 94 | }; 95 | } 96 | -------------------------------------------------------------------------------- /songs/iwashi/data.yml: -------------------------------------------------------------------------------- 1 | title: イワシがつちからはえてくるんだ 2 | titleComponents: 3 | - イワシが 4 | - つちから 5 | - はえてくるんだ 6 | artist: ころんば 7 | bpm: 135 8 | resolution: 32 9 | length: 3.1.0 10 | lyrics: | 11 | =7.1.0 12 | なんねん まえかの ことでした 13 | =8.4.0 14 | だれかが ハサミで 15 | =10.1.0 16 | タイムラインを ちょんぎった 17 | =11.4.5 18 | そして 19 | =12.3.0 20 | あしたと きのうが つながった 21 | =14.1.0 22 | 23 | =15.1.0 24 | あしたの ことは しっている 25 | =16.4.0 26 | イワシが つちから はえてくるんだ 27 | =19.1.0 28 | えきの ホームに あながあく 29 | =20.4.0 30 | すのこが きえるんだ 31 | =23.1.0 32 | きのうの きおくは きえたけど 33 | =24.4.0 34 | きえたってことも よくわからないんだ 35 | =27.1.0 36 | そらの うえから ビルがたつ 37 | =28.4.0 38 | めが みえなくなってきた 39 | 40 | =30.4.0 41 | はな は かれず 42 | =33.4.0 43 | とり は とばず ねむる 44 | =37.4.0 45 | かぜ は とまり つめたく 46 | =41.4.0 47 | つき は みちも かけも せず まわる 48 | =47.1.0 49 | 50 | =51.1.0 51 | いままでと これからが つながって 52 | =53.2.5 53 | いちにちを とばして わすれて 54 | =55.1.0 55 | すすんでく 56 | =55.4.5 57 | ここは 58 | =56.3.0 59 | もとには もどらなくなった 60 | =58.1.0 61 | 62 | =59.1.0 63 | あしたの ことは しっている 64 | =60.4.0 65 | イワシが つちから はえてくるんだ 66 | =63.1.0 67 | えきの ホームに あながあく 68 | =64.4.0 69 | すのこが きえるんだ 70 | =67.1.0 71 | きのうの きおくは きえたけど 72 | =68.4.0 73 | きえたってことも よくわからないんだ 74 | =71.1.0 75 | そらの うえから ビルがたつ 76 | =72.4.0 77 | めが みえなくなってきた 78 | 79 | =75.1.0 80 | あしたの ことは しっている 81 | =76.4.0 82 | イワシが つちから はえてくるんだ 83 | =79.1.0 84 | えきの ホームに あながあく 85 | =80.4.0 86 | すのこが きえるんだ 87 | =83.1.0 88 | きのうの きおくは きえたけど 89 | =84.4.0 90 | きえたってことも よくわからないんだ 91 | =87.1.0 92 | そらの うえから ビルがたつ 93 | =88.4.0 94 | めが みえなくなってきた 95 | =91.1.0 96 | clearances: 97 | - 7.1.0 98 | - 31.1.0 99 | - 47.1.0 100 | - 51.1.0 101 | - 59.1.0 102 | - 91.1.0 103 | vocals: 104 | yufu: 105 | - source: '01' 106 | start: 6.4.25 107 | end: 14.3.25 108 | - source: '02' 109 | start: 14.3.25 110 | end: 22.3.25 111 | - source: '03' 112 | start: 22.3.25 113 | end: 30.3.25 114 | - source: '04' 115 | start: 30.3.25 116 | end: 37.3.25 117 | - source: '05' 118 | start: 37.3.25 119 | end: 47.1.25 120 | - source: '06' 121 | start: 47.1.25 122 | end: 50.1.0 123 | - source: '07' 124 | start: 50.4.25 125 | end: 58.3.25 126 | - source: '02' 127 | start: 58.3.25 128 | end: 66.3.25 129 | - source: '03' 130 | start: 66.3.25 131 | end: 74.3.25 132 | - source: '02' 133 | start: 74.3.25 134 | end: 82.3.25 135 | - source: '03' 136 | start: 82.3.25 137 | end: 90.3.25 138 | - source: '08' 139 | start: 90.3.25 140 | end: 93.3.875 141 | defaultVocal: yufu 142 | backgrounds: 143 | - time: 0.1.0 144 | url: null 145 | workUrl: null 146 | title: null 147 | author: null 148 | license: null 149 | animation: null 150 | transform: null 151 | - time: 7.1.0 152 | url: https://farm5.staticflickr.com/4568/37574526294_a1137ffda6_k.jpg 153 | workUrl: https://flic.kr/p/ZfkgAf 154 | title: nature 155 | author: mouli choudari 156 | license: CC BY 157 | animation: left 158 | transform: null 159 | - time: 15.1.0 160 | url: https://farm4.staticflickr.com/3671/11285730373_f3e33590b1_k.jpg 161 | workUrl: https://flic.kr/p/ichjsa 162 | title: City 163 | author: reynermedia 164 | license: CC BY 165 | animation: right 166 | transform: null 167 | - time: 23.1.0 168 | url: https://farm4.staticflickr.com/3671/11285730373_f3e33590b1_k.jpg 169 | workUrl: https://flic.kr/p/ichjsa 170 | title: City 171 | author: reynermedia 172 | license: CC BY 173 | animation: left 174 | transform: rotate(180deg) 175 | - time: 31.1.0 176 | url: https://farm5.staticflickr.com/4146/5441757600_31068a25e2_b.jpg 177 | workUrl: https://flic.kr/p/9hSqWU 178 | title: A bird and apricot flowers 179 | author: bullets95 180 | license: CC BY-SA 181 | animation: right 182 | transform: null 183 | - time: 39.1.0 184 | url: https://farm5.staticflickr.com/4543/38135163096_57b0b9b8f2_b.jpg 185 | workUrl: https://flic.kr/p/216SFo1 186 | title: Beaver Moon Rise from Austin Texas 187 | author: Rob Pettengill 188 | license: CC BY-NC-ND 189 | animation: left 190 | transform: null 191 | - time: 48.1.0 192 | url: null 193 | workUrl: null 194 | title: null 195 | author: null 196 | license: null 197 | animation: null 198 | transform: null 199 | - time: 51.1.0 200 | url: https://farm5.staticflickr.com/4185/34571430632_eb91c0243f_b.jpg 201 | workUrl: https://flic.kr/p/UEXBSQ 202 | title: Nature 203 | author: Bernard Lacotte 204 | license: CC BY-NC-ND 205 | animation: up 206 | transform: null 207 | - time: 59.1.0 208 | url: https://farm4.staticflickr.com/3685/12708583543_7e491d6227_b.jpg 209 | workUrl: https://flic.kr/p/kn1P8n 210 | title: waiting for a train 211 | author: Keromi Keroyama 212 | license: CC BY 213 | animation: left 214 | transform: null 215 | - time: 67.1.0 216 | url: https://farm4.staticflickr.com/3685/12708583543_7e491d6227_b.jpg 217 | workUrl: https://flic.kr/p/kn1P8n 218 | title: waiting for a train 219 | author: Keromi Keroyama 220 | license: CC BY 221 | animation: right 222 | transform: rotate(180deg) 223 | - time: 75.1.0 224 | url: https://farm5.staticflickr.com/4119/4790098318_9d71f854ff_b.jpg 225 | workUrl: https://flic.kr/p/8ihvm3 226 | title: Diversify 227 | author: Thomas Hawk 228 | license: CC BY-NC 229 | animation: rotate 230 | transform: null 231 | - time: 91.1.0 232 | url: null 233 | workUrl: null 234 | title: null 235 | author: null 236 | license: null 237 | animation: null 238 | transform: null 239 | tracks: 240 | clap: 241 | type: percussion 242 | category: clap 243 | score: !require ./score/clap.txt 244 | default: 245 | sound: kinmoza-clap 246 | volume: 1 247 | snare: 248 | type: percussion 249 | category: snare 250 | score: !require ./score/snare.txt 251 | default: 252 | sound: karateka-kick 253 | volume: 0.5 254 | bass: 255 | type: percussion 256 | category: bass 257 | score: !require ./score/bass.txt 258 | default: 259 | sound: killme-pyonsuke 260 | volume: 0.6 261 | closed-hihat: 262 | type: percussion 263 | category: hihat 264 | score: !require ./score/closed-hihat.txt 265 | default: 266 | sound: ippon-crisp 267 | volume: 0.5 268 | base: 269 | type: instrument 270 | category: base 271 | score: !require ./score/base.txt 272 | default: 273 | sound: atsumori 274 | volume: 0.3 275 | chord: 276 | type: chord 277 | category: chorus 278 | score: !require ./score/chord.txt 279 | default: 280 | sound: aoba-zoi 281 | volume: 0.4 282 | cowbell: 283 | type: percussion 284 | category: bell 285 | score: !require ./score/cowbell.txt 286 | default: 287 | sound: zen-glass 288 | volume: 1 289 | chime1: 290 | type: percussion 291 | category: chime 292 | score: !require ./score/chime1.txt 293 | default: 294 | sound: inoubattle-otama 295 | volume: 0.6 296 | chime2: 297 | type: percussion 298 | category: chime 299 | score: !require ./score/chime2.txt 300 | default: 301 | sound: yukari-cowbell 302 | volume: 0.8 303 | chorus1: 304 | type: instrument 305 | category: chorus 306 | score: !require ./score/chorus1.txt 307 | intro: true 308 | default: 309 | sound: ai-virus 310 | volume: 0.2 311 | chorus2: 312 | type: instrument 313 | category: chorus 314 | score: !require ./score/chorus2.txt 315 | default: 316 | sound: jaguarman-waito 317 | volume: 0.2 318 | cymbal: 319 | type: percussion 320 | category: cymbal 321 | score: !require ./score/cymbal.txt 322 | default: 323 | sound: minecraft-creeper 324 | volume: 0.4 325 | chorus3: 326 | type: instrument 327 | category: chorus 328 | score: !require ./score/chorus3.txt 329 | default: 330 | sound: oreo-oh 331 | volume: 0.3 332 | chorus4: 333 | type: instrument 334 | category: chorus 335 | score: !require ./score/chorus4.txt 336 | default: 337 | sound: zkai-eh 338 | volume: 0.4 339 | synth1: 340 | type: instrument 341 | category: synth 342 | score: !require ./score/synth1.txt 343 | prank: true 344 | default: 345 | sound: washing-aegi 346 | volume: 0.4 347 | synth2: 348 | type: instrument 349 | category: synth 350 | score: !require ./score/synth2.txt 351 | prank: true 352 | default: 353 | sound: kemofure-toki 354 | volume: 0.2 355 | chorus5: 356 | type: instrument 357 | category: chorus 358 | score: !require ./score/chorus5.txt 359 | prank: true 360 | default: 361 | sound: chargeman-hai 362 | volume: 0.25 363 | chorus6: 364 | type: instrument 365 | category: chorus 366 | score: !require ./score/chorus6.txt 367 | prank: true 368 | default: 369 | sound: deremasu-suimasen 370 | volume: 0.4 371 | rap: 372 | type: rap 373 | start: 75.1.0 374 | end: 91.1.0 375 | default: 376 | sound: bemybaby-intro 377 | volume: 0.3 378 | -------------------------------------------------------------------------------- /songs/iwashi/icon.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d1a7ea0b3fd7782461353f73e11598b838ed7220009470877da070d4788309b7 3 | size 2864 4 | -------------------------------------------------------------------------------- /songs/iwashi/icon_raw.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6060e246d455fc084b9c77dc3a45062e5f8708ce7749c3034e0b02f7d81ab72a 3 | size 45578 4 | -------------------------------------------------------------------------------- /songs/iwashi/score/base.txt: -------------------------------------------------------------------------------- 1 | t135 o1 l8 2 | r1 r1 3 | 4 | /: d d >a< a >a< a :/3 5 | d r16 d r16 >a< d r d+4 6 | 7 | o1 l16 8 | d^ r d r >a^< r a >a< r a^ 9 | d^ r d r >a^< r a >a< r a^ 10 | g^ r g r c^ r c r 11 | f^ r f r f^ r f r 12 | e^ r e r >a^< r a >a< r a^ 13 | d^ r d r c^ r c r 14 | >a+^< r a+ d >a+< a+^ >a^< r a >a< r a^ 15 | o2 d^ r c+ r^ c r >b< r^^ >a^^^< 16 | 17 | o1 18 | /: 19 | d^ r d r c^ r c r 20 | >a+^< r a+ d >a+< a+^ f^ r f r 21 | g^ r g r c^ r c r 22 | f^ r f r f^ r f r 23 | >a+^< r a+ d >a+< a+^ >a^< r a >a< r a^ 24 | d^ r d r c^ r c r 25 | >g^< r g >g< r g^ c^ r c r 26 | | 27 | e^ r e r >a^< r a >a< r a^ 28 | :/2 29 | f^ r f r e^ r e r 30 | 31 | o1 l4 32 | >a+^^< r >a+^< c^ 33 | d^^ r c^ f^ 34 | >a+^^< r >a+^< >a^< 35 | d^^ r c^ f^ 36 | l8 37 | /: 38 | >a+< a+ >a+< a+ >a+< a+ >a+< a+ 39 | >a+< a+ >a+< a+ c c 40 | d d d d 41 | c c f f 42 | :/2 43 | 44 | o1 45 | /: d d >a< a >a< a :/3 46 | l16 47 | d^ r d^ r >a^< d^ r^ d+^^^ 48 | 49 | o1 l16 50 | d^ r d r >a^< r a >a< r a^ 51 | d^ r d r >a^< r a >a< r a^ 52 | g^ r g r c^ r c r 53 | f^ r f r f^ r f r 54 | e^ r e r >a^< r a >a< r a^ 55 | d^ r d r c^ r c r 56 | >a+^< r a+ d >a+< a+^ >a^< r a >a< r a^ 57 | o2 d^ r c+ r^ c r >b< r^^ >a^^^< 58 | 59 | o1 60 | /: 61 | d^ r d r c^ r c r 62 | >a+^< r a+ d >a+< a+^ f^ r f r 63 | g^ r g r c^ r c r 64 | f^ r f r f^ r f r 65 | >a+^< r a+ d >a+< a+^ >a^< r a >a< r a^ 66 | | 67 | d^ r d r c^ r c r 68 | >g^< r g >g< r g^ c^ r c r 69 | e^ r e r >a^< r a >a< r a^ 70 | :/2 71 | d^ r d r f^ r f r 72 | >g^< r g >g< r g^ c^ r c r 73 | f^ r f r e^ r e r 74 | 75 | o1 76 | /: 77 | d^ r d r c^ r c r 78 | >a+^< r a+ d >a+< a+^ f^ r f r 79 | g^ r g r c^ r c r 80 | f^ r f r f^ r f r 81 | >a+^< r a+ d >a+< a+^ >a^< r a >a< r a^ 82 | | 83 | d^ r d r c^ r c r 84 | >g^< r g >g< r g^ c^ r c r 85 | e^ r e r >a^< r a >a< r a^ 86 | :/2 87 | d^ r d r f^ r f r 88 | >g^< r g >g< r g^ c^ r c r 89 | f^ r f r e^ r e r 90 | 91 | l8 92 | /: d d >a< a >a< a :/3 93 | d^ a^ d 94 | -------------------------------------------------------------------------------- /songs/iwashi/score/bass.txt: -------------------------------------------------------------------------------- 1 | t135 o1 l4 2 | r1 r1 3 | 4 | /: c c c c :/3 l16 c^^ c^^ c^ c^^^ c^^^ 5 | 6 | l4 7 | /: c c c c :/4 8 | /: c c c c :/3 l16 c^^ c^^ c^ c^^^^^^^ 9 | 10 | l4 11 | /: c c c c :/16 12 | 13 | l16 14 | c^^c^^c^ c^^^^^^^ 15 | c^^^^cc^ ^^^^^^c^ 16 | c^^^^^c^ ^^^^^^^^ 17 | c^^^^cc^ ^^^^^^^^ 18 | c^^c^^c^ c^^^^^^^ 19 | c^^^^cc^ ^^^^^^c^ 20 | c^^^^^c^ ^^^^^^^^ 21 | c^^^^cc^ c^c^c^c^ 22 | l4 23 | /: c c c c :/8 24 | 25 | /: c c c c :/3 l16 c^^ c^^ c^ c^^^ c^^^ 26 | 27 | l4 28 | /: c c c c :/4 29 | /: c c c c :/3 l16 c^^ c^^ c^ c^^^ c^^^ 30 | 31 | l4 32 | /: c c c c :/16 33 | 34 | l4 35 | /: c c c c :/16 36 | 37 | /: c c c | c :/4 38 | -------------------------------------------------------------------------------- /songs/iwashi/score/chime1.txt: -------------------------------------------------------------------------------- 1 | t135 o1 l4 2 | r1 r1 3 | 4 | r1 r1 r1 l16 c^^ c^^ c^ r2 5 | 6 | l4 7 | /: c c r r :/7 l16 c^^ c^^ c^ r2 8 | 9 | l4 10 | /: c c r r :/16 11 | 12 | l1 13 | /: r :/16 14 | 15 | l4 16 | /: c c r r :/3 l16 c^^ c^^ c^ r2 17 | 18 | l4 19 | /: c c r r :/7 l16 c^^ c^^ c^ r2 20 | 21 | l4 22 | /: c c r r :/16 23 | 24 | l4 25 | /: c c r r :/16 26 | 27 | l4 28 | /: c c r r :/4 29 | -------------------------------------------------------------------------------- /songs/iwashi/score/chime2.txt: -------------------------------------------------------------------------------- 1 | t135 o1 l4 2 | r1 r1 3 | 4 | r1 r1 r1 r r c c 5 | 6 | /: r r c c :/8 7 | 8 | /: r r c c :/16 9 | 10 | l1 11 | /: r :/16 12 | 13 | l4 14 | /: r r c c :/4 15 | 16 | /: r r c c :/8 17 | 18 | /: r r c c :/16 19 | 20 | /: r r c c :/16 21 | 22 | /: r r c | c :/4 23 | -------------------------------------------------------------------------------- /songs/iwashi/score/chord.txt: -------------------------------------------------------------------------------- 1 | t135 o4 l4 2 | r1 r1 3 | 4 | /: r [dfa] r [ceg] :/3 5 | l8 6 | [dfa] r16 [dfa] r16 [>aa+a+aaaaa+a+aaaaa+a+aabaa+a+a+a+aaaaa+a+] r [ea] 28 | :/ 29 | r [>aaa+a+a+a+] 38 | l8 39 | r [>a+a+a+a+a+a+] r [fa] 43 | r [dfa+] r [dfa+] r [dfa+] r [dfa+] 44 | r [dfa+] r [dfa+] r [c+ea] r [c+ea] 45 | r [dfa] r [dfa] r [dfa] r [dfa] 46 | r [cd+g] r [cd+g] r [fa] r [fa] 47 | 48 | l4 49 | /: r [dfa] r [ceg] :/3 50 | l8 51 | [dfa] r16 [dfa] r16 [>aa+a+aaaaa+a+aaaaa+a+aabaa+a+a+a+aaaaa+a+] r [ea] 73 | :/ 74 | r [>aaa+a+a+a+a+a+aaaaa+a+] r [ea] 88 | :/ 89 | r [>aaa+a+aa^gf 5 | d^cdc^>aa+^^^< 25 | 26 | l1 27 | r r r r r r r l4 r r r g 28 | 29 | l2 v100 30 | /: 31 | a g f e f g c d+ 32 | d c a g f g | g a 33 | :/ 34 | f e 35 | 36 | l2 v100 37 | /: 38 | a g f e f g c d+ 39 | d c a g f g | g a 40 | :/ 41 | f e 42 | 43 | l1 44 | /: r :/4 45 | -------------------------------------------------------------------------------- /songs/iwashi/score/chorus2.txt: -------------------------------------------------------------------------------- 1 | t135 o4 l1 v50 2 | r1 r1 3 | 4 | r r r r 5 | 6 | r r r r r r r l4 r r r d 7 | 8 | l2 9 | /: 10 | f e d c d e c >a< 11 | e d e >a< c d | a e 12 | :/ 13 | c g 14 | 15 | l1 16 | /: r :/16 17 | 18 | l4 19 | /: f r e r :/3 20 | l16 21 | f^rfr^e^f^r^>f+^^^< 22 | 23 | l1 24 | r r r r r r r l4 r r r d 25 | 26 | l2 v100 27 | /: 28 | f e d c d e c >a< 29 | e d e >a< c d | a e 30 | :/ 31 | c g 32 | 33 | l2 v100 34 | /: 35 | f e d c d e c >a< 36 | e d e >a< c d | a e 37 | :/ 38 | c g 39 | 40 | l1 41 | /: r :/4 42 | -------------------------------------------------------------------------------- /songs/iwashi/score/chorus3.txt: -------------------------------------------------------------------------------- 1 | t135 o3 l1 2 | r1 r1 3 | 4 | /: r :/4 5 | 6 | /: r :/8 7 | 8 | /: r :/16 9 | 10 | l2 11 | d r d r 12 | f e g f 13 | d r d c 14 | f d c d+ 15 | d r d r 16 | f e g f 17 | d r d c 18 | f d c d+ 19 | 20 | l1 21 | /: r :/4 22 | 23 | l1 24 | /: r :/8 25 | 26 | o3 l8 v50 27 | /: 28 | a^^r g^ 29 | a^^r a^e^ 30 | f^^r g^f^ 31 | a^r^ a^fg16a16 32 | g^ e^fg 33 | f^f a^r^ 34 | a^ag aga 35 | a^^^ r^^^ 36 | :/2 37 | 38 | o3 l8 v50 39 | /: 40 | a^^r g^ 41 | a^^r a^e^ 42 | f^^r g^f^ 43 | a^r^ a^fg16a16 44 | g^ e^fg 45 | f^f a^r^ 46 | a^ag aga 47 | a^^^ r^^^ 48 | :/2 49 | 50 | l1 51 | /: r :/4 52 | -------------------------------------------------------------------------------- /songs/iwashi/score/chorus4.txt: -------------------------------------------------------------------------------- 1 | t135 o3 l1 2 | r1 r1 3 | 4 | /: r :/4 5 | 6 | /: r :/8 7 | 8 | /: r :/16 9 | 10 | l2 11 | f a f g 12 | a f a+ a 13 | f a f e 14 | a f e a 15 | f a f g 16 | a f a+ a 17 | f a f e 18 | a f e a 19 | 20 | l1 21 | /: r :/4 22 | 23 | l1 24 | /: r :/8 25 | 26 | o3 l8 v50 27 | /: 28 | a^^r g^ 29 | a^^r a^e^ 30 | f^^r g^fg 31 | a^r^ a^ef16g16 32 | a^g^ d^fg 33 | a^f^ e^r^ 34 | f^fe fefe 35 | d^^^ r^^^ 36 | :/2 37 | 38 | o3 l8 v50 39 | /: 40 | a^^r g^ 41 | a^^r a^e^ 42 | f^^r g^fg 43 | a^r^ a^ef16g16 44 | a^g^ d^fg 45 | a^f^ e^r^ 46 | f^fe fefe 47 | d^^^ r^^^ 48 | :/2 49 | 50 | l1 51 | /: r :/4 52 | -------------------------------------------------------------------------------- /songs/iwashi/score/chorus5.txt: -------------------------------------------------------------------------------- 1 | t135 o4 l1 2 | r1 r1 3 | 4 | /: r :/4 5 | 6 | /: r :/8 7 | 8 | /: r :/16 9 | 10 | /: r :/16 11 | 12 | /: r :/4 13 | 14 | l32 15 | r2 d^^^cdc^ >a^^^a^^^aa^^gaa< efec 23 | dr^^ ^^^^ 24 | 25 | l8 v40 26 | >aafg< 27 | >a^gaaaaafg< 31 | >a^gaaaaafg< 37 | >a^gaaaaafg< 41 | >a^gaaaa^ 17 | l8 18 | gr^^ ^^^^ 19 | r^da gfdf 20 | d^^r ^^^^ 21 | r^^^ ^ga 22 | a 23 | r^^ ^^^^ 24 | 25 | l8 v40 o4 26 | >aafg< 27 | >a^gaaaaafg< 31 | >a^gaaaaafg< 37 | >a^gaaaaafg< 41 | >a^gaaaa^g^f^^e^^ 14 | d^>aaaaaaaa^r^^^^^ ^^^^^^^^ 16 | r^^^^^^^ >bba^a^ 21 | :/4 22 | e< >g< v20 c e 38 | v35 >e< >g< v50 c e 39 | 40 | v60 41 | /: 42 | /: >a< d f a :/2 43 | /: >g< c e g :/2 44 | /: >a+< d f a :/2 45 | /: >a< c f a :/2 46 | /: d f g a+ :/2 47 | /: c e g a+ :/2 48 | /: >a< c f a :/2 49 | /: >a< c f a :/2 50 | /: >a+< d f a :/2 51 | /: >a< c e g :/2 52 | /: >a< c f a :/2 53 | /: >g< c e g :/2 54 | /: >a+< d f g :/2 55 | /: c e g a+ :/2 56 | | 57 | /: e g a+ :/2 58 | /: e a :/2 59 | :/2 60 | /: >a< c f a :/2 61 | /: >g< c e g :/2 62 | 63 | l1 64 | /: r :/4 65 | -------------------------------------------------------------------------------- /songs/iwashi/score/synth2.txt: -------------------------------------------------------------------------------- 1 | t135 o4 l1 2 | r1 r1 3 | 4 | /: r :/4 5 | 6 | /: r :/8 7 | 8 | /: r :/16 9 | 10 | /: 11 | o6 12 | l4 13 | r r r r 14 | l16 15 | g d >a< g d >a< f 16 | d r g >a< d g >a< f 17 | >a< f d g f r f a 18 | r r r r r r r r 19 | l4 20 | r r r r 21 | :/4 22 | 23 | l1 24 | /: r :/4 25 | 26 | l1 27 | /: r :/8 28 | 29 | l1 30 | /: r :/15 r2 31 | l16 32 | v10 >e< >g< v20 c e 33 | v35 >e< >g< v50 c e 34 | 35 | v60 36 | /: 37 | /: >a< d f a :/2 38 | /: >g< c e g :/2 39 | /: >a+< d f a :/2 40 | /: >a< c f a :/2 41 | /: d f g a+ :/2 42 | /: c e g a+ :/2 43 | /: >a< c f a :/2 44 | /: >a< c f a :/2 45 | /: >a+< d f a :/2 46 | /: >a< c e g :/2 47 | /: >a< c f a :/2 48 | /: >g< c e g :/2 49 | /: >a+< d f g :/2 50 | /: c e g a+ :/2 51 | | 52 | /: e g a+ :/2 53 | /: e a :/2 54 | :/2 55 | /: >a< c f a :/2 56 | /: >g< c e g :/2 57 | 58 | l1 59 | /: r :/4 60 | -------------------------------------------------------------------------------- /sound/Makefile: -------------------------------------------------------------------------------- 1 | WAV=$(shell find . -name '*.wav' -maxdepth 1 | sed 's/ /\\ /g') 2 | OGG=$(WAV:.wav=.ogg) 3 | 4 | .SECONDEXPANSION: 5 | %.ogg: $$(wildcard %.wav) 6 | ffmpeg -i "$*.wav" -b:a 96k -acodec libopus -f ogg "$@" -y 7 | 8 | all: $(OGG) 9 | -------------------------------------------------------------------------------- /sound/acchikocchi-sunoko.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:13f69adf1ec7d2476faa9f604158cd0c7c552b8fb0e8daca619c7c2686978e35 3 | size 3805 4 | -------------------------------------------------------------------------------- /sound/acchikocchi-sunoko.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:97d162039ea4e41489ececd2037c53cff2b1e05360bdc2a91cd4e50d9b9e225e 3 | size 76790 4 | -------------------------------------------------------------------------------- /sound/ai-virus.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:18a553176d47a72034f07683e4f733ff7aa99ad1914689cd71642c6d00e26f2d 3 | size 6022 4 | -------------------------------------------------------------------------------- /sound/ai-virus.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:af37fbc8e56191d3fff17570bdab89d0f3c3a51acfd764a8311e9bb70ea5fc55 3 | size 82428 4 | -------------------------------------------------------------------------------- /sound/aniplex-logo.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7f60b87957f63641e5c5c06bab7335119c502e23fc1cc15ca8132a692ce1aaac 3 | size 3652 4 | -------------------------------------------------------------------------------- /sound/aniplex-logo.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b6d3ae88330254c63acf862a92d1806ccd743dbb1379922d46f48ca39e8ec235 3 | size 34450 4 | -------------------------------------------------------------------------------- /sound/aoba-zoi.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1eede2825fd2ae67792886ffc9400009f1db6ee93534e7c44c50636c62916ef8 3 | size 10486 4 | -------------------------------------------------------------------------------- /sound/aoba-zoi.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f6527c7a9f9bde6d4862f10131363b355540ca04c20f7bb3a235ddf533009472 3 | size 122310 4 | -------------------------------------------------------------------------------- /sound/atsumori.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ab3fe1cfa769092ca125e9e59c28d270d5c8638ae9b594d451592b56e4b83b0b 3 | size 9381 4 | -------------------------------------------------------------------------------- /sound/atsumori.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:89ad08af8f7e26de6029fd616a2b70cc4de0360a1326b64b90c58d4f5d0da3e8 3 | size 153418 4 | -------------------------------------------------------------------------------- /sound/badapple-intro.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9d65412dd94dcb51d4fcac98b6eae6197bfd0936de4f4d86301594658bbcf472 3 | size 3067 4 | -------------------------------------------------------------------------------- /sound/badapple-intro.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ee31e15d78362bf75bcafe5774b82ce57a56a73bd551cfb2a72300f658086668 3 | size 39346 4 | -------------------------------------------------------------------------------- /sound/bemybaby-intro.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6ee9515a15db6092f6258550cd2c3d4bfc09b3cb419015b4f80a46403a36fad4 3 | size 87875 4 | -------------------------------------------------------------------------------- /sound/bemybaby-intro.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0aae4b957504a40210c02a95dee4be4eee8320d4ede10d8c18717090de2deb00 3 | size 1333460 4 | -------------------------------------------------------------------------------- /sound/chargeman-hai.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f71ab5f4506d8ff601acd115b2acac674dcf221ebad4e208cee0deae46439a80 3 | size 14348 4 | -------------------------------------------------------------------------------- /sound/chargeman-hai.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b9230fb97acf5969c90647467667c3553dff9211c0d59db78b52f1ab212832af 3 | size 200750 4 | -------------------------------------------------------------------------------- /sound/cheatbug-rakurai.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:23145a70b701be7ac796602e9ac7f1f124d8e5172b051367de81ef3e5a473193 3 | size 4852 4 | -------------------------------------------------------------------------------- /sound/cheatbug-rakurai.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:70bb9c0e6cc0f2e3e27e4f314b8ac145a60956062bd33c3f8777d5e0f05dcf32 3 | size 56908 4 | -------------------------------------------------------------------------------- /sound/chu2koi-au.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:143efd732dd1f70594a024d37b73d04a5b2336e30d04877374c7ab0eb1ed571b 3 | size 4909 4 | -------------------------------------------------------------------------------- /sound/chu2koi-au.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b3445f8080a2c597d0309bd70dbefcfb3136bc0078eafc3ba36ba79aa36e1338 3 | size 64922 4 | -------------------------------------------------------------------------------- /sound/chu2koi-stadiometer.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e696374ca8e47efbca71c4150e285a123155c1f2a9d3f3f9580721e3a3351d91 3 | size 3967 4 | -------------------------------------------------------------------------------- /sound/chu2koi-stadiometer.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8f358d2a5f7cfbafc77a905c78b22d5e565f61ac9fe2b3c791d7c939932b81d8 3 | size 56390 4 | -------------------------------------------------------------------------------- /sound/cookie-marisa.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f884c76c2581c3e53466a206a9f8fe97dc67316d05cc5ea5ae3e71dfe73f1d55 3 | size 2435 4 | -------------------------------------------------------------------------------- /sound/cookie-marisa.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e3d92a79d48bfe76f0230a6ec87d2682fb10f2f6a90f4b9d5b469c986a9a3efc 3 | size 26634 4 | -------------------------------------------------------------------------------- /sound/data.yml: -------------------------------------------------------------------------------- 1 | kinmoza-clap: 2 | type: percussion 3 | category: clap 4 | resource: 5 | work: きんいろモザイク 6 | name: 山手線ゲーム 7 | video: 8 | url: https://www.youtube.com/watch?v=STcc8H4Vr_g 9 | start: 5.4 10 | duration: 3 11 | karateka-kick: 12 | type: percussion 13 | category: snare 14 | resource: 15 | work: リズム天国 16 | name: カラテ家のパンチ 17 | video: 18 | url: https://www.youtube.com/watch?v=Cg6dlPZt-1g 19 | start: 32 20 | duration: 0.3 21 | killme-pyonsuke: 22 | type: percussion 23 | category: bass 24 | resource: 25 | work: キルミーベイベー 26 | name: ピョン助 27 | video: 28 | url: https://www.youtube.com/watch?v=WGecTmaeqjc 29 | start: 1100.5 30 | duration: 0.5 31 | ippon-crisp: 32 | type: percussion 33 | category: hihat 34 | resource: 35 | work: 一本満足バーCM 36 | name: 一本満足バー 37 | video: 38 | url: https://www.youtube.com/watch?v=2rc8CmeKinc 39 | start: 23.7 40 | duration: 1 41 | atsumori: 42 | type: instrument 43 | category: base 44 | loop: true 45 | sourceNote: 22 46 | prank: true 47 | resource: 48 | work: 熱盛放送事故 49 | name: 富川悠太アナ 50 | video: 51 | url: https://www.youtube.com/watch?v=uvg3I_IR9FA 52 | start: 4.8 53 | duration: 0.5 54 | aoba-zoi: 55 | type: instrument 56 | category: chorus 57 | loop: true 58 | sourceNote: 62 59 | resource: 60 | work: NEW GAME! 61 | name: 「今日も一日頑張るぞい」 62 | video: 63 | url: https://www.youtube.com/watch?v=DmZo4rL2E7E 64 | start: 18.9 65 | duration: 2 66 | zen-glass: 67 | type: percussion 68 | category: bell 69 | resource: 70 | work: 膳 71 | name: グラスを置く音 72 | video: 73 | url: https://www.youtube.com/watch?v=M_1UZlPBYzM 74 | start: 24.5 75 | duration: 0.5 76 | volume: 1 77 | minecraft-blaze: 78 | type: percussion 79 | category: chime 80 | resource: 81 | work: マインクラフト 82 | name: ブレイズ打撃音 83 | video: 84 | url: https://www.youtube.com/watch?v=tKt0oImbQ_Y 85 | start: 500.5 86 | duration: 1 87 | fireball-ring: 88 | type: percussion 89 | category: chime 90 | resource: 91 | work: ファイアボール 92 | name: ドロッセルお嬢様が床下よりご登場あそばされる時の音 93 | video: 94 | url: https://www.youtube.com/watch?v=6CQymHcBwWQ 95 | start: 477.5 96 | duration: 3 97 | ai-virus: 98 | type: instrument 99 | category: chorus 100 | loop: true 101 | sourceNote: 53 102 | resource: 103 | work: A.I.Channel 104 | name: ブラックアイちゃん感染音 105 | video: 106 | url: https://www.youtube.com/watch?v=4v3F3luBMEM 107 | start: 30.5 108 | duration: 3 109 | inazuma-pan: 110 | type: instrument 111 | category: chorus 112 | loop: false 113 | sourceNote: 64 114 | resource: 115 | work: アニメ艦これ 116 | name: 電の「ぱんぱかぱーん」 117 | video: 118 | url: https://www.youtube.com/watch?v=l3JuhAwx5aY 119 | start: 18 120 | duration: 1 121 | killme-cymbal: 122 | type: percussion 123 | category: cymbal 124 | resource: 125 | work: キルミーベイベー 126 | name: シンバル 127 | video: 128 | url: https://www.youtube.com/watch?v=Vv-SCTaw07w 129 | start: 36.2 130 | duration: 5 131 | oreo-oh: 132 | type: instrument 133 | category: chorus 134 | loop: true 135 | sourceNote: 50 136 | resource: 137 | work: ナビスコCM 138 | name: オレオ 139 | video: 140 | url: https://www.youtube.com/watch?v=lnpXXafCzj8 141 | start: 10.5 142 | duration: 1 143 | zkai-eh: 144 | type: instrument 145 | category: chorus 146 | loop: true 147 | sourceNote: 54 148 | resource: 149 | work: Z会CM 150 | name: 亀井有馬 151 | video: 152 | url: https://www.youtube.com/watch?v=e9ohRtZcOuo 153 | start: 38.3 154 | duration: 1 155 | washing-aegi: 156 | type: instrument 157 | category: synth 158 | loop: true 159 | sourceNote: 69 160 | prank: true 161 | resource: 162 | work: エロい洗濯機 163 | name: 喘ぎ声 164 | video: 165 | url: https://www.youtube.com/watch?v=w5xP4zHSQYI 166 | start: 10 167 | duration: 1 168 | kemofure-toki: 169 | type: instrument 170 | category: synth 171 | loop: true 172 | sourceNote: 97 173 | resource: 174 | work: けものフレンズ 175 | name: トキの歌声 176 | video: 177 | url: https://www.youtube.com/watch?v=jKo9p5VFMSE 178 | start: 24 179 | duration: 1 180 | chargeman-hai: 181 | type: instrument 182 | category: chorus 183 | loop: true 184 | sourceNote: 59 185 | prank: true 186 | resource: 187 | work: チャージマン研! 188 | name: No.12 189 | video: 190 | url: https://www.youtube.com/watch?v=Ih9uYOlrPpQ 191 | start: 179 192 | duration: 1 193 | deremasu-suimasen: 194 | type: instrument 195 | category: chorus 196 | loop: true 197 | sourceNote: 56 198 | prank: true 199 | resource: 200 | work: アニメ「アイドルマスターシンデレラガールズ」 201 | name: 「スイマセーン、そろそろ準備のほうお願いしますゥ^~↑」 202 | video: 203 | url: https://www.youtube.com/watch?v=7m7Wt75-js0 204 | start: 4 205 | duration: 1 206 | bemybaby-intro: 207 | type: rap 208 | tempo: 127 209 | duration: 4 210 | resource: 211 | work: BE MY BABY 212 | name: イントロ 213 | video: 214 | url: https://www.youtube.com/watch?v=WCIA678ybz8 215 | start: 3 216 | duration: 15 217 | rate: 1 218 | cheatbug-rakurai: 219 | type: instrument 220 | category: none 221 | loop: true 222 | sourceNote: 48 223 | resource: 224 | work: チートバグ動画 225 | name: 落雷フリーズ 226 | video: 227 | url: https://www.youtube.com/watch?v=5TVYvQqorxs 228 | start: 28.5 229 | duration: 1 230 | tennis-racket: 231 | type: percussion 232 | category: bell 233 | resource: 234 | work: テニスの王子様ミュージカル 235 | name: ラケット 236 | video: 237 | url: https://www.youtube.com/watch?v=YNZQDkbn9po 238 | start: 63.2 239 | duration: 1 240 | popute-asahi: 241 | type: instrument 242 | category: chorus 243 | loop: true 244 | sourceNote: 40 245 | resource: 246 | work: ポプテピピック 247 | name: 「アサヒィスゥパァドゥルァァァァイ」 248 | video: 249 | url: https://www.youtube.com/watch?v=LTBfw_zR_EA 250 | start: 17.7 251 | duration: 1 252 | legalhigh-anobade: 253 | type: instrument 254 | category: chorus 255 | loop: true 256 | sourceNote: 46 257 | resource: 258 | work: リーガルハイ 259 | name: 「あの場で言えていたらな~」 260 | video: 261 | url: https://www.youtube.com/watch?v=aWyzPaqwSrE 262 | start: 146 263 | duration: 1 264 | fgo-babbage: 265 | type: percussion 266 | category: hihat 267 | resource: 268 | work: Fate/GrandOrder 269 | name: チャールズ・バベッジ コマンドカード2 270 | video: 271 | url: https://www.youtube.com/watch?v=FT8blrOw_Pg 272 | start: 3.7 273 | duration: 0.5 274 | kemomimi-yononaka: 275 | type: instrument 276 | category: chorus 277 | loop: true 278 | sourceNote: 48 279 | resource: 280 | work: けもみみVRちゃんねる 281 | name: 「世の中世知辛いのじゃ~」 282 | video: 283 | url: https://www.youtube.com/watch?v=DoVh4Fc43Bo 284 | start: 75.5 285 | duration: 1.5 286 | inoubattle-otama: 287 | type: percussion 288 | category: chime 289 | resource: 290 | work: 異能バトルは日常系のなかで 291 | name: おたま 292 | video: 293 | url: https://www.youtube.com/watch?v=S7-P61KBPuQ 294 | start: 2 295 | duration: 1 296 | inoubattle-gasstove: 297 | type: percussion 298 | category: cymbal 299 | resource: 300 | work: 異能バトルは日常系のなかで 301 | name: ガスコンロ 302 | video: 303 | url: https://www.youtube.com/watch?v=S7-P61KBPuQ 304 | start: 11 305 | duration: 1 306 | acchikocchi-sunoko: 307 | type: percussion 308 | category: snare 309 | resource: 310 | work: あっちこっち 311 | name: スノコ 312 | video: 313 | url: https://www.youtube.com/watch?v=ulRAqGoeOHc 314 | start: 272 315 | duration: 0.5 316 | cookie-marisa: 317 | type: instrument 318 | category: chorus 319 | loop: true 320 | sourceNote: 64 321 | resource: 322 | work: 魔理沙とアリスのクッキーKiss 323 | name: 魔理沙 324 | video: 325 | url: https://www.youtube.com/watch?v=amP2mCqqPlQ 326 | start: 133.5 327 | duration: 1.5 328 | lovelive-shittofire: 329 | type: instrument 330 | category: chorus 331 | loop: true 332 | sourceNote: 53 333 | resource: 334 | work: ラブライブ!サンシャイン!! 335 | name: 「嫉妬ファイヤ~~~」 336 | video: 337 | url: https://www.youtube.com/watch?v=wvXuLfpkARA 338 | start: 18 339 | duration: 1 340 | maguro-drum: 341 | type: percussion 342 | category: bass 343 | resource: 344 | work: 「新春ドラマスペシャル・マグロ」番宣CM 345 | name: 太鼓 346 | video: 347 | url: https://www.youtube.com/watch?v=VfWgE7D1pYY 348 | start: 1 349 | duration: 1 350 | minecraft-creeper: 351 | type: percussion 352 | category: cymbal 353 | resource: 354 | work: Minecraft 355 | name: クリーパー 爆発音 356 | video: 357 | url: https://www.youtube.com/watch?v=8lndCdsxYCs 358 | start: 32.5 359 | duration: 1 360 | jaguarman-waito: 361 | type: instrument 362 | category: chorus 363 | prank: true 364 | sourceNote: 65 365 | resource: 366 | work: ジャガーマンシリーズ 367 | name: ワイト 368 | video: 369 | url: https://www.youtube.com/watch?v=rFneHF1kgtk 370 | start: 15.2 371 | duration: 1 372 | gintama-katsurap: 373 | type: rap 374 | tempo: 100 375 | duration: 4 376 | resource: 377 | work: 銀魂 378 | name: 桂ップ 379 | video: 380 | url: https://www.youtube.com/watch?v=DvS_2K5MVzU 381 | start: 10.1 382 | duration: 30 383 | rate: 1 384 | badapple-intro: 385 | type: percussion 386 | category: bass 387 | resource: 388 | work: BAD APPLE!! 389 | name: イントロ 390 | video: 391 | url: https://www.youtube.com/watch?v=9lNZ_Rnr7Jc 392 | start: 3 393 | duration: 0.5 394 | jajamen-wotagei: 395 | type: rap 396 | tempo: 170 397 | duration: 4 398 | resource: 399 | work: みっくす!じゃーじゃーめん 400 | name: ヲタ芸 401 | video: 402 | url: https://www.youtube.com/watch?v=PF15X3SOr0E 403 | start: 18 404 | duration: 6 405 | rate: 1 406 | kabuto-ketarosu: 407 | type: instrument 408 | category: chorus 409 | loop: true 410 | sourceNote: 55 411 | resource: 412 | work: 仮面ライダーカブト 413 | name: ケタロス 414 | video: 415 | url: https://www.youtube.com/watch?v=1Qr3Eem2hb4 416 | start: 4.2 417 | duration: 0.5 418 | matao-crossing: 419 | type: percussion 420 | category: crossing 421 | prank: true 422 | resource: 423 | work: 重大事故仮想再現VTR 424 | name: 踏切 425 | video: 426 | url: https://www.youtube.com/watch?v=YYkYwR3cosQ 427 | start: 100 428 | duration: 1 429 | nyancat-nya: 430 | type: instrument 431 | category: synth 432 | prank: true 433 | sourceNote: 66 434 | resource: 435 | work: Nyan Cat 436 | name: nya 437 | video: 438 | url: https://www.youtube.com/watch?v=QH2-TGUlwu4 439 | start: 4 440 | duration: 1 441 | nyanyanya-nya: 442 | type: instrument 443 | category: synth 444 | sourceNote: 66 445 | resource: 446 | work: Nyanyanyanyanyanyanya! 447 | name: nya 448 | video: 449 | url: https://www.youtube.com/watch?v=Til6kcoY0Yk 450 | start: 9 451 | duration: 1 452 | shachiku-biku: 453 | type: instrument 454 | category: chorus 455 | sourceNote: 38 456 | prank: true 457 | loop: true 458 | resource: 459 | work: いきのこれ!社畜ちゃん 460 | name: 「ビクッ」 461 | video: 462 | url: https://www.youtube.com/watch?v=de_VGQ7cFc8 463 | start: 89.8 464 | duration: 1 465 | shintakarajima-intro: 466 | type: instrument 467 | category: none 468 | prank: true 469 | sourceNote: 55 470 | resource: 471 | work: 新宝島 472 | name: イントロ 473 | video: 474 | url: https://www.youtube.com/watch?v=LIlZCmETvsY 475 | start: 9.3 476 | duration: 3 477 | shintakarajima-oh: 478 | type: percussion 479 | category: call 480 | resource: 481 | work: 新宝島 482 | name: 「OH!」 483 | video: 484 | url: https://www.youtube.com/watch?v=LIlZCmETvsY 485 | start: 62.5 486 | duration: 1 487 | yukari-cowbell: 488 | type: percussion 489 | category: bell 490 | resource: 491 | work: 何でも言うことを聞いてくれるアカネチャン 492 | name: カウベル 493 | video: 494 | url: https://www.youtube.com/watch?v=OVuYIMa5XBw 495 | start: 7.8 496 | duration: 0.5 497 | nichijo-kokeshi: 498 | type: percussion 499 | category: chime 500 | resource: 501 | work: 日常 502 | name: こけし 503 | video: 504 | url: https://www.youtube.com/watch?v=NnG1X8wBKww 505 | start: 22.3 506 | duration: 0.5 507 | nichijo-akabeko: 508 | type: percussion 509 | category: snare 510 | resource: 511 | work: 日常 512 | name: 赤べこ 513 | video: 514 | url: https://www.youtube.com/watch?v=NnG1X8wBKww 515 | start: 38.2 516 | duration: 0.5 517 | nichijo-shake: 518 | type: instrument 519 | category: chorus 520 | prank: true 521 | sourceNote: 39 522 | resource: 523 | work: 日常 524 | name: 「シャケだああああ」 525 | video: 526 | url: https://www.youtube.com/watch?v=NnG1X8wBKww 527 | start: 71.5 528 | duration: 1.5 529 | nichijo-eh: 530 | type: instrument 531 | category: chorue 532 | loop: true 533 | prank: true 534 | sourceNote: 35 535 | resource: 536 | work: 日常 537 | name: 「ええー……」 538 | video: 539 | url: https://www.youtube.com/watch?v=x2ypDDYDl70 540 | start: 172 541 | duration: 1 542 | nanami-jaan: 543 | type: instrument 544 | category: chorus 545 | prank: true 546 | sourceNote: 40 547 | resource: 548 | work: 窓辺ななみ 549 | name: 「じゃーん」 550 | video: 551 | url: https://www.youtube.com/watch?v=4blPBgc43cE 552 | start: 1.3 553 | duration: 1 554 | metan-ahoge: 555 | type: instrument 556 | category: chorus 557 | prank: true 558 | sourceNote: 41 559 | resource: 560 | work: ありがとう Me 561 | name: Meたんのアホ毛 562 | video: 563 | url: https://www.youtube.com/watch?v=M7A6ZTOhHXw 564 | start: 86 565 | duration: 0.5 566 | jojo-iwashi: 567 | type: instrument 568 | category: base 569 | loop: true 570 | sourceNote: 15 571 | resource: 572 | work: ジョジョの奇妙な冒険 未来への遺産HD 573 | name: 「イワシ」 574 | video: 575 | url: https://www.youtube.com/watch?v=RYZ3MuLXs98 576 | start: 98.6 577 | duration: 1 578 | enta-newwave: 579 | type: instrument 580 | category: chorus 581 | sourceNote: 46 582 | resource: 583 | work: エンタの神様 584 | name: 「次々と新しい仕掛けを生み出し続けるのは、この男~!」 585 | video: 586 | url: https://www.youtube.com/watch?v=cFhMmTnkpBA 587 | start: 85 588 | duration: 1 589 | chu2koi-au: 590 | type: instrument 591 | category: synth 592 | sourceNote: 48 593 | resource: 594 | work: 中二病でも恋がしたい! 595 | name: 「あぅ」 596 | video: 597 | url: https://www.youtube.com/watch?v=ik0O_hrbN5E 598 | start: 67.8 599 | duration: 0.5 600 | chu2koi-stadiometer: 601 | type: percussion 602 | category: cowbell 603 | resource: 604 | work: 中二病でも恋がしたい! 605 | name: 身長計 606 | video: 607 | url: https://www.youtube.com/watch?v=ik0O_hrbN5E 608 | start: 10 609 | duration: 0.5 610 | saronshippu-ah: 611 | type: instrument 612 | category: chorus 613 | sourceNote: 40 614 | resource: 615 | work: サロンシップCM 616 | name: 竹中直人 617 | video: 618 | url: https://www.youtube.com/watch?v=kU8FUxmZvIQ 619 | start: 8.3 620 | duration: 0.5 621 | evangelion-crack: 622 | type: percussion 623 | category: hihat 624 | resource: 625 | work: 新世紀エヴァンゲリオン 626 | name: ガラス 627 | video: 628 | url: https://www.youtube.com/watch?v=_uNNRs19EzQ 629 | start: 6 630 | duration: 0.5 631 | evangelion-clap: 632 | type: percussion 633 | category: clap 634 | resource: 635 | work: 新世紀エヴァンゲリオン 636 | name: 拍手 637 | video: 638 | url: https://www.youtube.com/watch?v=_uNNRs19EzQ 639 | start: 28.2 640 | duration: 0.5 641 | kabikiller-rah: 642 | type: instrument 643 | category: chorus 644 | sourceNote: 36 645 | resource: 646 | work: カビキラーCM 647 | name: カビキラー 648 | video: 649 | url: https://www.youtube.com/watch?v=bjdStMwsiWY 650 | start: 1.8 651 | duration: 0.5 652 | prestar-yuupack: 653 | type: percussion 654 | category: cowbell 655 | resource: 656 | work: Prestar 657 | name: ゆうパック 658 | video: 659 | url: https://www.youtube.com/watch?v=IFUCYtKynL0 660 | start: 18.6 661 | duration: 0.5 662 | donkeykong-hammer: 663 | type: instrument 664 | category: synth 665 | sourceNote: 48 666 | resource: 667 | work: ドンキーコング 668 | name: ハンマー状態 669 | video: 670 | url: https://www.youtube.com/watch?v=3tIC9Oftva4 671 | start: 5 672 | duration: 0.5 673 | seirogan-trumpet: 674 | type: instrument 675 | category: wind 676 | sourceNote: 52 677 | resource: 678 | work: 正露丸CM 679 | name: ラッパ 680 | video: 681 | url: https://www.youtube.com/watch?v=x6MK9pCWkG4 682 | start: 6.8 683 | duration: 1 684 | sakanakun-akyaa: 685 | type: instrument 686 | category: synth 687 | sourceNote: 67 688 | resource: 689 | work: さかなクン 690 | name: 「あきゃーっ」 691 | video: 692 | url: https://www.youtube.com/watch?v=pdJRY8Mv0kU 693 | start: 79.8 694 | duration: 1 695 | suntelevision-ossan: 696 | type: instrument 697 | category: chorus 698 | prank: true 699 | sourceNote: 28 700 | resource: 701 | work: サンテレビCM 702 | name: おっ!サンテレビ 703 | video: 704 | url: https://www.youtube.com/watch?v=jMCz1LQFP-w 705 | start: 71.5 706 | duration: 1 707 | aniplex-logo: 708 | type: instrument 709 | category: synth 710 | loop: true 711 | sourceNote: 48 712 | resource: 713 | work: アニプレックス 714 | name: サウンドロゴ 715 | video: 716 | url: https://www.youtube.com/watch?v=LubTx0WpVFU 717 | start: 2.2 718 | duration: 1 719 | deremasu-mashumaro: 720 | type: percussion 721 | category: none 722 | resource: 723 | work: アニメ「アイドルマスターシンデレラガールズ」 724 | name: マシュマロ砲 725 | video: 726 | url: https://www.youtube.com/watch?v=ExT9cr9hcWI 727 | start: 141.3 728 | duration: 0.5 729 | kokoro-bookoff: 730 | type: instrument 731 | category: synth 732 | loop: false 733 | prank: true 734 | sourceNote: 75 735 | resource: 736 | work: BOOKOFF CM「心を読める心くん」 737 | name: 「ブックオフなのに本ねえじゃん」 738 | video: 739 | url: https://www.youtube.com/watch?v=JH1Ns-FTTVQ 740 | start: 5.5 741 | duration: 1 742 | gochiusa-tippy-no: 743 | type: instrument 744 | category: base 745 | loop: false 746 | prank: true 747 | sourceNote: 77 748 | resource: 749 | work: アニメ「ご注文はうさぎですか?」 750 | name: ティッピー「ノー!」 751 | video: 752 | url: https://www.youtube.com/watch?v=Eg2uYxL7NVk 753 | start: 106.5 754 | duration: 2 755 | -------------------------------------------------------------------------------- /sound/deremasu-mashumaro.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d6e401e758138d3daee892e84444309585646a3d05c14b379c7727c25bb585d7 3 | size 4045 4 | -------------------------------------------------------------------------------- /sound/deremasu-mashumaro.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f5d0f84ac57856e1b73e33fd46019e72d8dc7b7d4a045aeb8f2dd4f2d351d056 3 | size 60726 4 | -------------------------------------------------------------------------------- /sound/deremasu-suimasen.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4acfbd9a542cf813616246f283aa73240491b37743c87ac25c3d9908b7975437 3 | size 5548 4 | -------------------------------------------------------------------------------- /sound/deremasu-suimasen.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d226ce9155382ada504c0413c1e560507dfacc6dc19663706de68aa29003b768 3 | size 60398 4 | -------------------------------------------------------------------------------- /sound/donkeykong-hammer.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f04ad71212a7db70620e80759e4853bbbae01c33ad87a44ddfc5d5a4dda19fb3 3 | size 1985 4 | -------------------------------------------------------------------------------- /sound/donkeykong-hammer.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:06d1925d93be073c302f49586af17be38f0deb8d0f69b55dcd2fced7e7828084 3 | size 16414 4 | -------------------------------------------------------------------------------- /sound/enta-newwave.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cd6d76835524e9f4b193a8cda5812c4c78c8541da228a28587a246707156f7dc 3 | size 12253 4 | -------------------------------------------------------------------------------- /sound/enta-newwave.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f3d8ceffdfbae6e67a9072accc78193edf1cb374055a19d91f886091d3fc7edf 3 | size 145094 4 | -------------------------------------------------------------------------------- /sound/evangelion-clap.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c9188d0b7fa921f8c4091a95e20187cb5948a8eb7fac72c2ce9f00dd7b3021ae 3 | size 2013 4 | -------------------------------------------------------------------------------- /sound/evangelion-clap.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f595a16288f099d569868b5aff3fd947beb58adbe58c6c7ea4d5f6dc9c45ec53 3 | size 18958 4 | -------------------------------------------------------------------------------- /sound/evangelion-crack.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3bdd8993c52ea0ad59d833491bd081866aad62ffc9ab942958e5c2c1b8a2c6a9 3 | size 2614 4 | -------------------------------------------------------------------------------- /sound/evangelion-crack.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5159e07cb730731e5406cd57a0313eb399392f429edfb2905f2bf6a879d0b189 3 | size 34970 4 | -------------------------------------------------------------------------------- /sound/fgo-babbage.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a90e45852b77d90170ac57ef8ecabd96fcde1c712882a6db6e0e83b403f23d9e 3 | size 11549 4 | -------------------------------------------------------------------------------- /sound/fgo-babbage.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b0fce341faba1861fb1de729e5d8eaa51b1e87f9dc772ebcd0a39d308e816f7c 3 | size 172454 4 | -------------------------------------------------------------------------------- /sound/fireball-ring.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:46070fb64ffe40bdf0dd075a2ff590db36b3fe05f86a7ce08aaa3d28469c877f 3 | size 11196 4 | -------------------------------------------------------------------------------- /sound/fireball-ring.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5fccb1e30532b744ba2e4fef1280c11bfb10368995ecf5748745d333b737b911 3 | size 151282 4 | -------------------------------------------------------------------------------- /sound/gintama-katsurap.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4524b63e4afe4d4942cba06a35e7dd18cda0f7297f935672055ad21945ec0af6 3 | size 115428 4 | -------------------------------------------------------------------------------- /sound/gintama-katsurap.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:db3ede25c41f5e7f8e66772764a778b831c0f8e7b7141ce2084e6177c1b86a40 3 | size 846870 4 | -------------------------------------------------------------------------------- /sound/gochiusa-tippy-no.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a90da54390002c0755869791de532826c59706e6925ba6b715d2a9c3a6f1fcf2 3 | size 23846 4 | -------------------------------------------------------------------------------- /sound/gochiusa-tippy-no.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fdf63348d6e4ac5b826d6c5664a892fb57f7ca6c15f3ea69a695258af24b57ea 3 | size 356454 4 | -------------------------------------------------------------------------------- /sound/hitodeman-hea.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ac49b4ee44fba13089718c6087f9b5a430cb3178ab849b8849de0878393b12b1 3 | size 5562 4 | -------------------------------------------------------------------------------- /sound/hitodeman-hea.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e5d28ef7084665d292030e2e1a5458f73a795ecf4c70f58b8b487c5d685912b7 3 | size 61642 4 | -------------------------------------------------------------------------------- /sound/inazuma-pan.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:456fc1e72ba99c24a6e8e23e0a24e9722e2d7f3975ad62b30d0030dd37313216 3 | size 20796 4 | -------------------------------------------------------------------------------- /sound/inazuma-pan.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b9527958d9d2da73fd3a460f0b6e93e587d715e0b32bb685d1d518c6d7858e41 3 | size 280078 4 | -------------------------------------------------------------------------------- /sound/inoubattle-gasstove.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a499923a8fce57357964610d171e5fdb164b1448db79484cc43a2e1d9bd1739a 3 | size 5567 4 | -------------------------------------------------------------------------------- /sound/inoubattle-gasstove.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:670f45bb8636be94ba43eff3d4956ed10e8a8163bd5e802f0d3df9efc9e93ac9 3 | size 116414 4 | -------------------------------------------------------------------------------- /sound/inoubattle-otama.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:19722455afe51310a5c221f40cd93c827d6e27b536a04e0f6d628d8ba1068fd5 3 | size 2454 4 | -------------------------------------------------------------------------------- /sound/inoubattle-otama.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f40730ba1985857400cd81dfb0b8dedb446810150d6911adafbcec451c3f7fbe 3 | size 37022 4 | -------------------------------------------------------------------------------- /sound/ippon-crisp.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d98078b3808ca65f72a32ecf72d632c66a5e38900e8c9d3d081d8497b3fab360 3 | size 1701 4 | -------------------------------------------------------------------------------- /sound/ippon-crisp.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c784f62af20745c15ddeb16a0a81032827b4de86675956021babc4eebd381317 3 | size 19214 4 | -------------------------------------------------------------------------------- /sound/jaguarman-waito.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:740b125fdce8be58023ad898780bd52e8f2f9d67b6ebb75f72546c67ce826608 3 | size 16927 4 | -------------------------------------------------------------------------------- /sound/jaguarman-waito.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:86d907cbe94d6d181fcb638c7ff9d64f0405d535653cb334a2054962599628af 3 | size 208146 4 | -------------------------------------------------------------------------------- /sound/jajamen-wotagei.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:77832950ef9fbcb1c7e90d5023dcb88a1cdbb4aa2066d62bbe538fd59c69a0d5 3 | size 68124 4 | -------------------------------------------------------------------------------- /sound/jajamen-wotagei.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f2d911406ae47cfbfcca7583f4d73f6490b0969a66411d708c4f2ed02b854d30 3 | size 498806 4 | -------------------------------------------------------------------------------- /sound/jojo-iwashi.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:df893e5f60feb8af0638051310c160f8dd04fe2b63e3270826ac71bc01c75e37 3 | size 2353 4 | -------------------------------------------------------------------------------- /sound/jojo-iwashi.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d9805e1aa0ca8a80af54379b81f17e4764c1836e962cd5499b22ea4952317833 3 | size 31258 4 | -------------------------------------------------------------------------------- /sound/kabikiller-rah.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2ac36680b0d976c741ea5224410f614c52024f8d48b53af88e4f481e000d6766 3 | size 10201 4 | -------------------------------------------------------------------------------- /sound/kabikiller-rah.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e81119e89546b1c4161f17bd25753b782fef9a9ba4c9d00179ca66707eb7a32f 3 | size 137966 4 | -------------------------------------------------------------------------------- /sound/kabuto-ketarosu.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1967b809a3844c1d0cb7025c6cdc5f63931392b311cb91cf0987784c99278a3e 3 | size 2794 4 | -------------------------------------------------------------------------------- /sound/kabuto-ketarosu.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:48ee2d7069aefd87684644d111d7736f91f102181cee360871b250cd00d4f1e6 3 | size 42662 4 | -------------------------------------------------------------------------------- /sound/karateka-kick.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d33883f1c93b68c88c7f59c1b10f57736ee32f4ad6d41689633ab22880aeaff2 3 | size 3239 4 | -------------------------------------------------------------------------------- /sound/karateka-kick.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:270426e25b23fc1219011c4c39a4611a1dbb085df66a329fe6f9d696b395cb89 3 | size 52426 4 | -------------------------------------------------------------------------------- /sound/kemofure-toki.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:97145923d81b1f701b0203fbc7edcdd333c31a6017ca08d77b56e732d13271a9 3 | size 7552 4 | -------------------------------------------------------------------------------- /sound/kemofure-toki.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b27db1a91a938b1b87ebb87d8dd212a19f6d3d83ffea7d51bf9fa3d05a76c884 3 | size 65738 4 | -------------------------------------------------------------------------------- /sound/kemomimi-yononaka.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:00c11ef3c0ad521aca365ea4bcd67e9d1917df208309a221e4ac81af5fc2db36 3 | size 3346 4 | -------------------------------------------------------------------------------- /sound/kemomimi-yononaka.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b99b08936a628d3592d616482df98d95ee3d045deedd89e684feb69f3ec8a0b3 3 | size 35794 4 | -------------------------------------------------------------------------------- /sound/killme-cymbal.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:002fedbffd732c27557d274c15bf51a9bf3e355b3674c4368c4523f1bda7e862 3 | size 36907 4 | -------------------------------------------------------------------------------- /sound/killme-cymbal.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7d98e61958782785a23ce67a79fb0e51153b5468b14f69cd60f3dd86244f1335 3 | size 306550 4 | -------------------------------------------------------------------------------- /sound/killme-pyonsuke.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:404763778f133fdc3f4f42519a9fc6ff865a5b4e992e2c0de501aa3e6b28979a 3 | size 2943 4 | -------------------------------------------------------------------------------- /sound/killme-pyonsuke.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b5e3593ed0866f37343b7830343f491acd8a7d403719573ad79e90df63f53c4c 3 | size 57886 4 | -------------------------------------------------------------------------------- /sound/kinmoza-clap.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cb136d711c3da7c0d636488a143ebe997f026c49834b2a862a03b1e69bd2462d 3 | size 2292 4 | -------------------------------------------------------------------------------- /sound/kinmoza-clap.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3bbeb1e703078bb446583c1693ec4eddfe5ecc6125c000b4e9c36181c6ef58fd 3 | size 26114 4 | -------------------------------------------------------------------------------- /sound/kokoro-bookoff.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c1e9cd07fae9df7c0a2aa4c016c5fbfee047806d48af58b7adc385bdd6351962 3 | size 9676 4 | -------------------------------------------------------------------------------- /sound/kokoro-bookoff.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f4b0b354efbac8d68f3a8f296ca0aab1f3a60f32e8cb2acf0c06d1c3e4dade01 3 | size 42464 4 | -------------------------------------------------------------------------------- /sound/legalhigh-anobade.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eb8ec1ebab4075435b556435ab81ade44eb8af1b2c6a9d891042abbd567dcc94 3 | size 3531 4 | -------------------------------------------------------------------------------- /sound/legalhigh-anobade.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:af87eefa370d093f5f24949808f6dcc40d21c3fcb591675e7ff83746b7c89b70 3 | size 36988 4 | -------------------------------------------------------------------------------- /sound/lovelive-shittofire.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:443f771343b74225002df4701d6808cc66edc2c43d6975a59ebfae9fe4fd85c1 3 | size 3865 4 | -------------------------------------------------------------------------------- /sound/lovelive-shittofire.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5cd12fa266978d0d23437a135fb71c4ee4a4618db3137a11addfdf3c016fb6f4 3 | size 48050 4 | -------------------------------------------------------------------------------- /sound/maguro-drum.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:30072da3a7eb42950b54e3bf21afdb645eea1df73ca9d3a967ae78465d303533 3 | size 19128 4 | -------------------------------------------------------------------------------- /sound/maguro-drum.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:45e9992694d819efd8ca50294a2a34bfb332f65c8d2b73c39243ec075f73d946 3 | size 257662 4 | -------------------------------------------------------------------------------- /sound/matao-crossing.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4be8cd02562fb0bf6ce375856549bac7c5f9028ab37fd0ab65bf5d25bd7ede13 3 | size 5291 4 | -------------------------------------------------------------------------------- /sound/matao-crossing.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7f02630ded0cb8b749a1e1f7fd48fc0e4f6ed46a2146b634d17a6e04d1739ffe 3 | size 84974 4 | -------------------------------------------------------------------------------- /sound/metan-ahoge.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3ad2aec93b69007d465c0d596e0f5ab8427db1a9f82a5f57ae62c8136c731b42 3 | size 2625 4 | -------------------------------------------------------------------------------- /sound/metan-ahoge.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9d052914dee85c7c19e11bfc273e8532fab1b9b9a361347d7d4e1de6902df994 3 | size 33562 4 | -------------------------------------------------------------------------------- /sound/minecraft-blaze.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a74e88366aa2301bfd395436af5724dd9efcb6102cd54ddd0758b4772a90daf3 3 | size 5761 4 | -------------------------------------------------------------------------------- /sound/minecraft-blaze.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eee176c9487835957fd47560e6b1973a4c76a4e02f2a0eecd1612d3b43a5d672 3 | size 89274 4 | -------------------------------------------------------------------------------- /sound/minecraft-creeper.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:374a7e2f85e5d760e73ff22d40f97fc827d256deef39e0c02acfd260376cb62c 3 | size 14896 4 | -------------------------------------------------------------------------------- /sound/minecraft-creeper.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ebebbbf0e286555a3e9b52ced53c2316f9172ab06a37760a52129201a59dbbe8 3 | size 225018 4 | -------------------------------------------------------------------------------- /sound/nanami-jaan.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:883b65c6486bd02c7b57a15e658bc6b0170ae390e3bd1b6cd36ad9e4d282f15a 3 | size 20114 4 | -------------------------------------------------------------------------------- /sound/nanami-jaan.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:454a95e776e3249c046cf413e2641f0c41f5e0da3eb8672bd4d0c6d98270c5cf 3 | size 251372 4 | -------------------------------------------------------------------------------- /sound/nichijo-akabeko.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a97f8488d0184323c8208e7136123ad48deff06709f397f2fac71bf9528318d8 3 | size 5414 4 | -------------------------------------------------------------------------------- /sound/nichijo-akabeko.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fae5ae69d38193821d6e7c820289f5f807d9baa1c64134b48dabb9a22c5dc167 3 | size 94550 4 | -------------------------------------------------------------------------------- /sound/nichijo-eh.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ce632afec4819cf2f0fb72dd5bc2ec46ab1fe9140e1139a9d7d02b01a8186c89 3 | size 2303 4 | -------------------------------------------------------------------------------- /sound/nichijo-eh.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7cc4935280f311bb8ada2d2d7f6333ea4a5fc1e90c0ece8ea32f17ba35e65243 3 | size 19446 4 | -------------------------------------------------------------------------------- /sound/nichijo-kokeshi.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:46df8ff8b2829a0b092719b338eef75f8517a6703e582aa7fa5033ac235680ea 3 | size 6315 4 | -------------------------------------------------------------------------------- /sound/nichijo-kokeshi.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:078ca4f4d4a2545616e16448d7df60a3df582b3492550aa3fc957ddb70811166 3 | size 106806 4 | -------------------------------------------------------------------------------- /sound/nichijo-shake.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:22b77d93f7758f3ae80f8ff3d4db20ba05ba7977b09832e56db8ab043c5822e7 3 | size 28570 4 | -------------------------------------------------------------------------------- /sound/nichijo-shake.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ad970a5ef61477e976af8ba186c50080d68d7f311940e800930e6fbb6a40343f 3 | size 301744 4 | -------------------------------------------------------------------------------- /sound/nyancat-nya.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ef4aac22cd21a223f0baca84cb8fd91059f04aa05173b356d934f20a20273c32 3 | size 5336 4 | -------------------------------------------------------------------------------- /sound/nyancat-nya.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b148768581e91ae62c59f549b385a025b2af32934e897be7ab8d63702cccc261 3 | size 48910 4 | -------------------------------------------------------------------------------- /sound/nyanyanya-nya.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0672a2967e45ba6fda5986561b27db1ae1c7153ee31f7f9a4b326bda4dc02dd7 3 | size 2975 4 | -------------------------------------------------------------------------------- /sound/nyanyanya-nya.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c5d0ff2cc73fff84e9f892643c4f3f8a74b0e4079bb3b4b3277401f8880d83a2 3 | size 33882 4 | -------------------------------------------------------------------------------- /sound/oreo-oh.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:247f7cc6edfc1c15cd3d70170e50917b2ce06bedd21d51a9818f5d1720767b40 3 | size 3520 4 | -------------------------------------------------------------------------------- /sound/oreo-oh.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f07fd2f5710801e4d719d8f23ffabf3604843f9d1fb6ba3c8912297382a8bac0 3 | size 38952 4 | -------------------------------------------------------------------------------- /sound/popute-asahi.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ca70dbed1a2769fc7213972d0e34352a3451f01e98bb4fbc53f74c143457d74f 3 | size 2074 4 | -------------------------------------------------------------------------------- /sound/popute-asahi.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2b9c7cec21d36aa5849d43844e8e215d2a9cacc1088a2b3f5f630fc48c54fbec 3 | size 23786 4 | -------------------------------------------------------------------------------- /sound/prestar-yuupack.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b33e5d440b5bf07c38298ce30f469a8ae7a4f40b1b020932ba2abde92275bf84 3 | size 2258 4 | -------------------------------------------------------------------------------- /sound/prestar-yuupack.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:256b91a811e9bae4326c48772ce7830d1de21b04301c3bd8ddde6cfd1064ea76 3 | size 27962 4 | -------------------------------------------------------------------------------- /sound/rizap-cm.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:02c2b39833bf8e1a238a797d65b2ac467d00cb0936fd91932daa043e4702bdb6 3 | size 6856 4 | -------------------------------------------------------------------------------- /sound/rizap-cm.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5a177b7c0363c1630c8861c1f28c5d69ed3bcd4b09f7d97ed6907cc2ee24222f 3 | size 92258 4 | -------------------------------------------------------------------------------- /sound/sakanakun-akyaa.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b8fb3ded62b513cb0f8819955075cf4c0c393f26d175fad26d822f8aae0a1243 3 | size 5591 4 | -------------------------------------------------------------------------------- /sound/sakanakun-akyaa.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b68e66cfa1e38fc68fbffe73ba3ad5fe073945ccf8585062a6cc8d4cc1883a47 3 | size 79706 4 | -------------------------------------------------------------------------------- /sound/saronshippu-ah.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1be3b78d96741fca6231f765053cf4808afef103f5619700671343d00ea6d64a 3 | size 10049 4 | -------------------------------------------------------------------------------- /sound/saronshippu-ah.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:937fedf4b68d43ad14c153b24de8887b313bc5a29308bb944aa56f5fe8a65e49 3 | size 123030 4 | -------------------------------------------------------------------------------- /sound/seirogan-trumpet.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3e521b2952241fdb12551712942fed03b7136168849e07462e5aa83ee0c6dbf1 3 | size 12246 4 | -------------------------------------------------------------------------------- /sound/seirogan-trumpet.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:56d799f679f464a12ce10e25248b31ca6cc8dcd4c0e1c6f096ac100c4f23655e 3 | size 139304 4 | -------------------------------------------------------------------------------- /sound/shachiku-biku.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f4da42eb186a5ce3c7d720d627e028ca2be50c24ed1428f1bf3e781237989366 3 | size 1266 4 | -------------------------------------------------------------------------------- /sound/shachiku-biku.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a77dfcc916adcb0083b7178b0d261b044c2de848bddb5c47a39a4e867a94de3c 3 | size 9710 4 | -------------------------------------------------------------------------------- /sound/shintakarajima-intro.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:92889a0eb519b4ab7e65123024986923e615e271d073ef43c4e4173db45a484c 3 | size 22213 4 | -------------------------------------------------------------------------------- /sound/shintakarajima-intro.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d6314a728dddecce085b01474e4cd84a1951f5cb95609fa4fca60d19965bf91c 3 | size 264542 4 | -------------------------------------------------------------------------------- /sound/shintakarajima-oh.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9e9da5cb292a0e83a951d4556ba5db050bdd5e4a85ee056c3a47f90894d065e1 3 | size 6641 4 | -------------------------------------------------------------------------------- /sound/shintakarajima-oh.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2fb4db06ea763fd908e10c4f4d1a93ad4a59780a48b6a990f1543c3493d179a4 3 | size 84616 4 | -------------------------------------------------------------------------------- /sound/suntelevision-ossan.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:55a0e1406cd5e4950ad7eb0d8d000bfb065e7ee5890332f4caa6a01b0d9f3ffa 3 | size 15949 4 | -------------------------------------------------------------------------------- /sound/suntelevision-ossan.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b95f23e64ebb9f2ced22e1ce8d4abaf4e90e9dc7278bd440dbf26afbdd32d679 3 | size 216834 4 | -------------------------------------------------------------------------------- /sound/tennis-racket.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eec3cea3e09da4c23707392d9b45a287607fd3b8e312457be3b478f28cf64b23 3 | size 11972 4 | -------------------------------------------------------------------------------- /sound/tennis-racket.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:38b82bf68821285b7f9ecdaeefc672533962ecb4f4350e018af9936a63a22805 3 | size 73706 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/01.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fb72033127d395e4d56264b5c51634a33c7fd736b551faf82f34ba18368f7abe 3 | size 165385 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/01.ust: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2dfaa1ee9f2a58d64fe6c24e0a1ba88fe85686062d5b7205e90356c72fb8260b 3 | size 8779 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/01.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e8f0c1496541911f9c0e5af79b6877e95260683fa066e5297cbab8000d7dc08a 3 | size 1143704 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/02.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d48f64b424ff7635c7cf2de63701c9fd298cf89bb463b37621ebd3d641081dd7 3 | size 187265 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/02.ust: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b703f56fb4c960c7da9277bc3e4579e6ae18c76d74a28d2321c62decba34efb5 3 | size 10410 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/02.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:652f15ef6cae830bcc0b5ba7bc662c790f25e21e6e5833ea03b5feba0b4bd4d3 3 | size 1280902 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/03.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:90e8d8d0cbbd9a520b540b12aa843740c9c7246a1203f9a6ba19985e827e8650 3 | size 189283 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/03.ust: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4f248de2e2fe325925417cb6116065f8fbfe6e86d6ff38aece7c3350a37f22ff 3 | size 9773 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/03.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d4f4577eb5aa1cc43ecb36b3b5e2c479ae59b40f0a9c1520c657bf10a8c41f68 3 | size 1280904 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/04.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:569ba7d21c24085d4f20c1032775da652906a2e0264d94f514831b08c85d4fa4 3 | size 168378 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/04.ust: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8c70775e05cd4a276c252b54cf21ff0473202afd11addf82db2731fb19752e4b 3 | size 2735 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/04.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:93b3fc963df19fed68c03717b46f2f1038f44c905f26bb11beca70c141fc7796 3 | size 1085626 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/05.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:51545f964441de99e8afa31c1653e988c4195b34ecba6a179c4a9edbc9737c24 3 | size 228716 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/05.ust: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1774fdeddbd809427945c3d66eb3d037a73b4c0affe069cced0bfb142b9a1edc 3 | size 4271 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/05.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0028559a20ad9a7d04fde4bce229808de9ecd41fd45e563f5532fd3bea44bd39 3 | size 1477654 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/06.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3cf5fd9821b98958506c25c386fe8373ef97b6bfdd318f014b76380fc1874d03 3 | size 76451 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/06.ust: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1922eb111e887472b4dea5f3024ba2c0ac2955541cb7c4c8c7d16f08f07e6634 3 | size 2305 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/06.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:846f68c1601bd3ca441d6c90de55ab55e4b6ca45135b3516522546557afe6121 3 | size 604704 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/07.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8c234f7480b1ce43637a203b31570e976d698bc42c52e5c5626931c31d7b36ba 3 | size 164802 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/07.ust: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a407dc7b0ab2a56f2ae84da0f055a9b087622c9c410c6298fdba8ccd7f1460b6 3 | size 8339 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/07.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:87e9f5af7e7f2c67e955bdaad37bc09438764cff4c2bf3ac59e5e1c197dce1da 3 | size 1182904 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/08.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:aa8db862e79f959effef1064a71b1660eb910dad79ca09b71c9d8a713893b87a 3 | size 78431 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/08.ust: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:511fac8c9c0da875d2d4aa28a495723f9c93e5b6013983b69aaa49ffe4b0d924 3 | size 2388 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/08.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d7a4e93aff3cf3d8f4e63b7412cdcc24b17209e6aaaa196c85442044ddfcb2aa 3 | size 1347268 4 | -------------------------------------------------------------------------------- /sound/vocal/yufu/character.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0b054443ba3d412fe05abe408d4c7f7d86efcc48a7821d355ca9fd8d00da972d 3 | size 35656 4 | -------------------------------------------------------------------------------- /sound/washing-aegi.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ebe455a8428f67d35fea3c4fa29329b178fb911e718ee18b732fc1706447a962 3 | size 3207 4 | -------------------------------------------------------------------------------- /sound/washing-aegi.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ee887bd7a173801ac79e3adca33ee45e6c29a76e41be5a3ac1a751c75e471da1 3 | size 47914 4 | -------------------------------------------------------------------------------- /sound/yukari-cowbell.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0fc4cf81856de772a87915ad2a8775592c486270b0025d6b959654a0a14c2089 3 | size 3614 4 | -------------------------------------------------------------------------------- /sound/yukari-cowbell.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f2ef0f75aa3a4f6c78696826edb15ece026690aa6678f538dcecb460b80ea721 3 | size 50818 4 | -------------------------------------------------------------------------------- /sound/yuyushiki-nantsutte.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ba10e16553d1d3f22706b53a02ba222fcecfb002d3e382841a0ed6b1ed4f842f 3 | size 213916 4 | -------------------------------------------------------------------------------- /sound/yuyushiki-nantsutte.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1a2e435cfdb64672555520c368558b5eb8b06efdffee37cc8c9dcb6c65b2742b 3 | size 2822444 4 | -------------------------------------------------------------------------------- /sound/zen-glass.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e79279a90e0456faf286b1d187866839359e96d1c0fb151894b6ce47615d17e7 3 | size 2166 4 | -------------------------------------------------------------------------------- /sound/zen-glass.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:28e006d2a74e498b4de3cb9fcb2f1eacabab2c73a6c158796a1442ab117a0d23 3 | size 24746 4 | -------------------------------------------------------------------------------- /sound/zkai-eh.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f1cbe0562c47d49721a327ea110bfbfc41314175f0cdc6164ab682dcd1b47270 3 | size 6046 4 | -------------------------------------------------------------------------------- /sound/zkai-eh.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:176a52ec162f42cbc157e9e661f328a59008d9d5d4145b57e11e053581365b2a 3 | size 60414 4 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const qs = require('querystring'); 3 | const React = require('react'); 4 | const classNames = require('classnames'); 5 | const PropTypes = require('prop-types'); 6 | const shuffle = require('lodash/shuffle'); 7 | const get = require('lodash/get'); 8 | const Modernizr = require('modernizr'); 9 | // eslint-disable-next-line node/no-missing-require 10 | const createjs = require('imports-loader?this=>window!exports-loader?window.createjs!preloadjs/lib/preloadjs'); 11 | 12 | import './App.pcss'; 13 | import { 14 | FaFacebook, 15 | FaGithub, 16 | FaPause, 17 | FaPlay, 18 | FaStepBackward, 19 | FaStepForward, 20 | FaTwitter, 21 | } from 'react-icons/fa'; 22 | import { 23 | MdRefresh, 24 | MdShare, 25 | MdUndo, 26 | MdVideocam, 27 | MdVideocamOff, 28 | } from 'react-icons/md'; 29 | // eslint-disable-next-line node/no-extraneous-require 30 | const {default: Hatena} = require('hatena-icon/hatenabookmark-logomark.svg'); 31 | 32 | const {TICK} = require('./const.js'); 33 | const VocalManager = require('./VocalManager.js'); 34 | const {getResourceUrl, wait, isMobile, Deferred} = require('./util.js'); 35 | const songs = require('../songs/index.js'); 36 | const params = require('./params.js'); 37 | const gist = require('./gist.js'); 38 | const Track = require('./Track.jsx'); 39 | const Loading = require('./Loading.jsx'); 40 | const VolumeControls = require('./VolumeControls.jsx'); 41 | const SoundSelect = require('./SoundSelect.jsx'); 42 | const Tooltip = require('./Tooltip.jsx'); 43 | 44 | class ShareIcon extends React.Component { 45 | static propTypes = { 46 | name: PropTypes.oneOf(['twitter', 'hatena', 'facebook']).isRequired, 47 | isArrange: PropTypes.bool.isRequired, 48 | children: PropTypes.oneOfType([ 49 | PropTypes.arrayOf(PropTypes.node), 50 | PropTypes.node, 51 | ]).isRequired, 52 | onClick: PropTypes.func.isRequired, 53 | }; 54 | 55 | handleClick = (event) => { 56 | this.props.onClick(this.props.name, this.props.isArrange, event); 57 | }; 58 | 59 | render() { 60 | return ( 61 |
65 | {this.props.children} 66 |
67 | ); 68 | } 69 | } 70 | 71 | module.exports = class App extends React.Component { 72 | static propTypes = { 73 | // eslint-disable-next-line react/forbid-prop-types 74 | gistData: PropTypes.any, 75 | }; 76 | 77 | static defaultProps = { 78 | gistData: null, 79 | }; 80 | 81 | constructor(props) { 82 | super(props); 83 | 84 | this.song = songs.iwashi; 85 | 86 | this.vocalManagerPromise = VocalManager.initialize( 87 | this.song.vocals, 88 | this.song.defaultVocal 89 | ); 90 | this.backgroundDeferred = new Deferred(); 91 | 92 | this.tracks = shuffle(Object.entries(this.song.tracks)); 93 | 94 | this.initBackground(); 95 | 96 | this.selectedSound = null; 97 | this.isInitialized = false; 98 | this.clearedIntervals = new Set(); 99 | 100 | const size = (() => { 101 | if (isMobile()) { 102 | return 'small'; 103 | } 104 | 105 | if (window.innerWidth <= 1366) { 106 | return 'small'; 107 | } 108 | 109 | if (window.innerWidth < 1920) { 110 | return 'normal'; 111 | } 112 | 113 | return 'large'; 114 | })(); 115 | 116 | this.state = { 117 | beat: null, 118 | lyric: '', 119 | soloScore: null, 120 | trackStatuses: new Map(this.tracks.map(([name]) => [name, 'loading'])), 121 | trackSounds: new Map( 122 | this.tracks.map(([name, track]) => [ 123 | name, 124 | { 125 | sound: String( 126 | get( 127 | this.props.gistData, 128 | ['songs', 0, 'tracks', name, 'sound'], 129 | track.default.sound 130 | ) 131 | ), 132 | volume: Number( 133 | get( 134 | this.props.gistData, 135 | ['songs', 0, 'tracks', name, 'volume'], 136 | track.default.volume 137 | ) 138 | ), 139 | muted: Boolean( 140 | get( 141 | this.props.gistData, 142 | ['songs', 0, 'tracks', name, 'muted'], 143 | false 144 | ) 145 | ), 146 | solo: Boolean( 147 | get( 148 | this.props.gistData, 149 | ['songs', 0, 'tracks', name, 'solo'], 150 | false 151 | ) 152 | ), 153 | pan: 0, 154 | }, 155 | ]) 156 | ), 157 | size, 158 | soundSelect: false, 159 | soundSelectTop: 0, 160 | soundSelectLeft: 0, 161 | vocalVolume: 0.6, 162 | background: this.song.backgrounds[0], 163 | backgroundAnimation: null, 164 | backgroundDuration: null, 165 | shareName: '', 166 | flashCount: 0, 167 | isFlashing: false, 168 | isNoVideo: true, 169 | isReady: false, 170 | isIntro: false, 171 | isPaused: false, 172 | isPlayReady: false, 173 | isVocalDisabled: false, 174 | isVocalSolo: false, 175 | isShareOpen: false, 176 | }; 177 | 178 | // Modernizr.audioautoplay is async check and we have to manually check if ready 179 | const checkModernizrInterval = setInterval(() => { 180 | if (Modernizr.audioautoplay !== undefined) { 181 | clearInterval(checkModernizrInterval); 182 | 183 | if (Modernizr.audioautoplay === true) { 184 | this.setState({isPlayReady: true}); 185 | } 186 | } 187 | }, 100); 188 | } 189 | 190 | initBackground = () => { 191 | const queue = new createjs.LoadQueue(); 192 | queue.loadManifest( 193 | this.song.backgrounds.map((b) => b.url).filter((url) => url !== null) 194 | ); 195 | queue.addEventListener('fileload', () => { 196 | // Resolves when the first background image is preloaded 197 | if (!this.backgroundDeferred.isResolved) { 198 | this.backgroundDeferred.resolve(); 199 | } 200 | }); 201 | }; 202 | 203 | pause = () => { 204 | if (this.state.isPaused) { 205 | return; 206 | } 207 | clearInterval(this.handleBeatInterval); 208 | this.clearedIntervals.add(this.handleBeatInterval); 209 | this.vocalManager.pause(); 210 | this.setState({isPaused: true}); 211 | }; 212 | 213 | unpause = () => { 214 | if (!this.state.isPaused) { 215 | return; 216 | } 217 | if (this.clearedIntervals.has(this.handleBeatInterval)) { 218 | this.handleBeatInterval = setInterval(this.handleBeat, TICK * 1000); 219 | } 220 | this.vocalManager.unpause(); 221 | this.setState({isPaused: false}); 222 | }; 223 | 224 | handleBeat = () => { 225 | this.setState(({beat}) => ({beat: beat === null ? TICK * 0 : beat + TICK})); 226 | 227 | const beat = Math.floor(this.state.beat / TICK); 228 | if (beat >= this.song.length) { 229 | clearInterval(this.handleBeatInterval); 230 | return; 231 | } 232 | this.vocalManager.onBeat(beat); 233 | 234 | const lyric = this.song.lyrics.find( 235 | ({start, end}) => start <= beat && beat < end 236 | ); 237 | if (!lyric && this.state.lyric !== '') { 238 | this.setState({ 239 | lyric: '', 240 | }); 241 | } 242 | 243 | if (lyric && this.state.lyric !== lyric.text) { 244 | this.setState({ 245 | lyric: lyric.text, 246 | }); 247 | } 248 | 249 | if (!isMobile()) { 250 | for (const [index, background] of this.song.backgrounds.entries()) { 251 | if (background.time === beat) { 252 | const nextBackground = this.song.backgrounds[index + 1]; 253 | 254 | new Promise((resolve) => { 255 | this.setState( 256 | { 257 | background, 258 | backgroundAnimation: null, 259 | backgroundDuration: 260 | nextBackground && 261 | ((((nextBackground.time - background.time) / 262 | this.song.resolution) * 263 | 4) / 264 | this.song.bpm) * 265 | 60, 266 | }, 267 | resolve 268 | ); 269 | }) 270 | .then(() => wait(0)) 271 | .then(() => { 272 | // this.setState({backgroundAnimation: background.animation}); 273 | }); 274 | break; 275 | } 276 | } 277 | } 278 | }; 279 | 280 | handleSoundStatusChanged = async (name, status) => { 281 | this.setState(({trackStatuses}) => ({ 282 | trackStatuses: trackStatuses.set(name, status), 283 | })); 284 | 285 | if ( 286 | this.state.soundSelect === false && 287 | Array.from(this.state.trackStatuses.values()).every((s) => s === 'ready') 288 | ) { 289 | if (this.isInitialized) { 290 | this.unpause(); 291 | } else { 292 | this.isInitialized = true; 293 | 294 | const [vocalManager] = await Promise.all([ 295 | this.vocalManagerPromise, 296 | this.backgroundDeferred.promise, 297 | ]); 298 | 299 | this.vocalManager = vocalManager; 300 | 301 | if (!params.debug) { 302 | await wait(1000); 303 | } 304 | 305 | this.setState({ 306 | isReady: true, 307 | isIntro: true, 308 | }); 309 | 310 | if (params.debug) { 311 | this.handleIntroEnded(); 312 | } 313 | } 314 | } 315 | }; 316 | 317 | handleChangeCheckbox = () => { 318 | this.setState(({isNoVideo}) => ({isNoVideo: !isNoVideo})); 319 | }; 320 | 321 | handleFlash = async () => { 322 | if (isMobile()) { 323 | return; 324 | } 325 | 326 | await new Promise((resolve) => { 327 | this.setState( 328 | ({flashCount}) => ({ 329 | isFlashing: false, 330 | flashCount: flashCount + 1, 331 | }), 332 | resolve 333 | ); 334 | }); 335 | 336 | await wait(0); 337 | 338 | this.setState({ 339 | isFlashing: true, 340 | isIntro: false, 341 | }); 342 | }; 343 | 344 | handleChangeSolo = (score, isSolo) => { 345 | if (isSolo) { 346 | this.vocalManager.enableNotSolo(); 347 | } else { 348 | this.vocalManager.disableNotSolo(); 349 | } 350 | 351 | this.setState({ 352 | soloScore: isSolo ? score : null, 353 | isVocalDisabled: this.vocalManager.isNotSolo || this.vocalManager.isMuted, 354 | ...(isSolo ? {isVocalSolo: false} : {}), 355 | }); 356 | }; 357 | 358 | handleChangeVoiceMuted = (isMuted) => { 359 | if (isMuted) { 360 | this.vocalManager.mute(); 361 | } else { 362 | this.vocalManager.unmute(); 363 | } 364 | 365 | this.setState({ 366 | isVocalDisabled: this.vocalManager.isNotSolo || this.vocalManager.isMuted, 367 | }); 368 | }; 369 | 370 | handleChangeVoiceVolume = (volume) => { 371 | this.vocalManager.setVolume(volume); 372 | this.setState({ 373 | vocalVolume: this.vocalManager.volume, 374 | }); 375 | }; 376 | 377 | handleChangeVoiceSolo = (isSolo) => { 378 | if (isSolo && this.state.isVocalDisabled) { 379 | this.vocalManager.unmute(); 380 | this.vocalManager.disableNotSolo(); 381 | } 382 | 383 | this.setState({ 384 | isVocalSolo: isSolo, 385 | ...(isSolo 386 | ? { 387 | isVocalDisabled: false, 388 | soloScore: null, 389 | } 390 | : {}), 391 | }); 392 | }; 393 | 394 | handleClickPause = () => { 395 | if (this.state.isPaused) { 396 | this.unpause(); 397 | } else { 398 | this.pause(); 399 | } 400 | }; 401 | 402 | handleClickChange = (name, target) => { 403 | this.selectedSound = this.state.trackSounds.get(name).sound; 404 | this.setState({ 405 | soundSelect: name, 406 | soundSelectTop: target.offsetTop + target.offsetHeight / 2, 407 | soundSelectLeft: target.offsetLeft + target.offsetWidth / 2, 408 | }); 409 | this.pause(); 410 | }; 411 | 412 | handleClickBackdrop = () => { 413 | const selectedTrack = this.state.soundSelect; 414 | 415 | this.setState({soundSelect: false}); 416 | 417 | if ( 418 | this.selectedSound === this.state.trackSounds.get(selectedTrack).sound 419 | ) { 420 | if ( 421 | Array.from(this.state.trackStatuses.values()).every( 422 | (s) => s === 'ready' 423 | ) 424 | ) { 425 | this.unpause(); 426 | } 427 | } else { 428 | this.setState(({trackSounds}) => ({ 429 | trackSounds: trackSounds.set(selectedTrack, { 430 | ...trackSounds.get(selectedTrack), 431 | sound: this.selectedSound, 432 | }), 433 | })); 434 | } 435 | }; 436 | 437 | handleSoundSelect = (name) => { 438 | this.selectedSound = name; 439 | }; 440 | 441 | handleClickOk = () => { 442 | this.setState({isPlayReady: true}); 443 | }; 444 | 445 | handleClickDefault = () => { 446 | this.setState({ 447 | trackSounds: new Map( 448 | this.tracks.map(([name, track]) => [ 449 | name, 450 | { 451 | sound: track.default.sound, 452 | volume: track.default.volume, 453 | muted: false, 454 | solo: false, 455 | pan: 0, 456 | }, 457 | ]) 458 | ), 459 | }); 460 | this.pause(); 461 | }; 462 | 463 | handleUpdateTrack = (name, track) => { 464 | this.setState(({trackSounds}) => ({ 465 | trackSounds: trackSounds.set(name, track), 466 | })); 467 | }; 468 | 469 | handleIntroEnded = () => { 470 | assert(this.state.isIntro === true); 471 | this.handleBeatInterval = setInterval(this.handleBeat, TICK * 1000); 472 | }; 473 | 474 | handleClickShare = () => { 475 | this.setState(({isShareOpen}) => ({isShareOpen: !isShareOpen})); 476 | }; 477 | 478 | handleRequestCloseShare = () => { 479 | this.setState({isShareOpen: false}); 480 | }; 481 | 482 | handleShareNameChange = (event) => { 483 | this.setState({shareName: event.target.value}); 484 | }; 485 | 486 | handleClickShareIcon = async (name, isArrange) => { 487 | const path = await (async () => { 488 | if (isArrange === false) { 489 | return '/'; 490 | } 491 | 492 | const content = { 493 | version: 1, 494 | transcriber: this.state.shareName, 495 | songs: [ 496 | { 497 | song: 'iwashi', 498 | vocal: { 499 | sound: 'yufu', 500 | volume: 1, 501 | muted: false, 502 | solo: false, 503 | pan: 0, 504 | }, 505 | tracks: Object.assign( 506 | ...Array.from(this.state.trackSounds).map(([track, value]) => ({ 507 | [track]: value, 508 | })) 509 | ), 510 | jingles: [], 511 | }, 512 | ], 513 | }; 514 | 515 | const gistId = await gist.post({ 516 | description: 517 | '音MAD自動演奏サイト「iwashi」アレンジデータ #iwashi https://hakatashi.github.io/iwashi/', 518 | filename: 'iwashi-score.json', 519 | content, 520 | }); 521 | 522 | return `/?gist=${gistId}`; 523 | })(); 524 | 525 | const url = `https://hakatashi.github.io/iwashi${path}`; 526 | 527 | const titleText = (() => { 528 | if (isArrange) { 529 | if (this.state.shareName) { 530 | return `${this.state.shareName}さんが「${ 531 | this.song.title 532 | }」をアレンジしました!`; 533 | } 534 | 535 | return `「${this.song.title}」をアレンジしました!`; 536 | } 537 | 538 | return ''; 539 | })(); 540 | 541 | const title = titleText ? `${titleText} ${document.title}` : document.title; 542 | 543 | const intent = (() => { 544 | if (name === 'twitter') { 545 | return `https://twitter.com/intent/tweet?${qs.encode({ 546 | text: title, 547 | url, 548 | hashtags: 'iwashi', 549 | })}`; 550 | } 551 | 552 | if (name === 'facebook') { 553 | return `https://www.facebook.com/sharer/sharer.php?${qs.encode({ 554 | u: url, 555 | })}`; 556 | } 557 | 558 | assert(name === 'hatena'); 559 | return `http://b.hatena.ne.jp/add?${qs.encode({ 560 | mode: 'confirm', 561 | url, 562 | title, 563 | })}`; 564 | })(); 565 | 566 | open(intent, 'share', 'width=600,height=400'); 567 | 568 | if (isArrange) { 569 | history.replaceState(null, null, path); 570 | } 571 | }; 572 | 573 | render() { 574 | return ( 575 |
581 | this.state.trackStatuses.get(name))} 589 | name="iwashi" 590 | vanishing={this.state.isReady} 591 | isPlayReady={this.state.isPlayReady} 592 | onClickOk={this.handleClickOk} 593 | /> 594 |
595 |
605 |
612 |
613 |
614 |
615 | {this.tracks.map(([name, track]) => ( 616 | 643 | ))} 644 |
645 | {this.state.soundSelect && ( 646 | 647 |
648 | 658 | 659 | )} 660 |
661 |
662 |
663 | 669 | 675 | かえる 676 | 677 |
678 |
{this.state.lyric}
679 |
680 | 688 |
689 | {this.state.background.author && ( 690 |
691 | 背景:{' '} 692 | 697 | {this.state.background.title} 698 | {' '} 699 | by {this.state.background.author} 700 |
701 | )} 702 |
703 |
704 |
705 |
706 | 707 | 708 | 709 |
710 | {this.state.isPaused ? : } 711 |
712 | 713 | 714 | 715 |
716 |
717 | ♪{this.song.title}/{this.song.artist} 718 | 723 | かえる 724 | 725 |
726 |
727 | 730 |
731 | このサイトをシェアする 732 |
733 |
734 | 739 | 740 | 741 | 746 | 747 | 748 | 753 | 754 | 755 |
756 |
757 | このアレンジをシェアする 758 |
759 |
760 | {'「'} 761 | 767 | {'さんによるアレンジ」'} 768 |
769 |
770 | 775 | 776 | 777 | 782 | 783 | 784 |
785 |
786 | } 787 | interaction 788 | interactive 789 | open={this.state.isShareOpen} 790 | style={{width: '100%', height: '100%'}} 791 | onRequestClose={this.handleRequestCloseShare} 792 | arrow 793 | animateFill={false} 794 | > 795 | 796 | 797 |
798 |
799 | 803 | 804 | 805 |
806 |
812 | 820 | {this.state.isNoVideo ? : } 821 | 822 |
823 | 829 | 833 | 834 | 835 | 836 |
837 |
838 | ); 839 | } 840 | }; 841 | -------------------------------------------------------------------------------- /src/App.pcss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: misaki; 3 | src: url('../node_modules/misaki-font/misaki_gothic.ttf') format('woff'); 4 | } 5 | 6 | html, 7 | body, 8 | .app { 9 | margin: 0; 10 | width: 100%; 11 | height: 100%; 12 | overflow: hidden; 13 | } 14 | 15 | body { 16 | font-family: misaki; 17 | } 18 | 19 | svg { 20 | vertical-align: middle; 21 | } 22 | 23 | .app { 24 | width: 100%; 25 | height: 100%; 26 | 27 | display: flex; 28 | flex-direction: column; 29 | 30 | &.flash::after { 31 | content: ''; 32 | position: absolute; 33 | top: 0; 34 | left: 0; 35 | right: 0; 36 | bottom: 0; 37 | 38 | background: white; 39 | opacity: 0; 40 | 41 | pointer-events: none; 42 | animation: app-after-animation 0.6s linear; 43 | will-change: opacity; 44 | 45 | @at-root { 46 | @keyframes app-after-animation { 47 | from { 48 | opacity: 0.6; 49 | } 50 | to { 51 | opacity: 0; 52 | } 53 | } 54 | } 55 | } 56 | 57 | &.intro { 58 | .tracks, 59 | .lyric { 60 | visibility: hidden; 61 | } 62 | } 63 | } 64 | 65 | .main { 66 | flex: 1 0 0; 67 | height: 0; 68 | position: relative; 69 | 70 | display: flex; 71 | flex-direction: column; 72 | } 73 | 74 | .background { 75 | position: absolute; 76 | top: 0; 77 | left: 0; 78 | right: 0; 79 | bottom: 0; 80 | 81 | animation-timing-function: linear; 82 | animation-fill-mode: both; 83 | animation-duration: 5s; 84 | will-change: transform; 85 | 86 | z-index: -1; 87 | 88 | $distance: 300px; 89 | 90 | &.right { 91 | top: 0; 92 | left: -$distance; 93 | right: 0; 94 | bottom: 0; 95 | animation-name: background-right-animation; 96 | 97 | @at-root { 98 | @keyframes background-right-animation { 99 | from { 100 | transform: translateX(0px); 101 | } 102 | to { 103 | transform: translateX($distance); 104 | } 105 | } 106 | } 107 | } 108 | 109 | &.left { 110 | top: 0; 111 | left: 0; 112 | right: -$distance; 113 | bottom: 0; 114 | animation-name: background-left-animation; 115 | 116 | @at-root { 117 | @keyframes background-left-animation { 118 | from { 119 | transform: translateX(0px); 120 | } 121 | to { 122 | transform: translateX(-$distance); 123 | } 124 | } 125 | } 126 | } 127 | 128 | &.up { 129 | top: 0; 130 | left: 0; 131 | right: 0; 132 | bottom: -$distance; 133 | animation-name: background-up-animation; 134 | 135 | @at-root { 136 | @keyframes background-up-animation { 137 | from { 138 | transform: translateY(0px); 139 | } 140 | to { 141 | transform: translateY(-$distance); 142 | } 143 | } 144 | } 145 | } 146 | 147 | &.down { 148 | top: -$distance; 149 | left: 0; 150 | right: 0; 151 | bottom: 0; 152 | animation-name: background-down-animation; 153 | 154 | @at-root { 155 | @keyframes background-down-animation { 156 | from { 157 | transform: translateY(0px); 158 | } 159 | to { 160 | transform: translateY($distance); 161 | } 162 | } 163 | } 164 | } 165 | 166 | &.rotate { 167 | top: calc(-1 * (141.42vmax - 100%) / 2); 168 | left: calc(-1 * (141.42vmax - 100%) / 2); 169 | right: calc(-1 * (141.42vmax - 100%) / 2); 170 | bottom: calc(-1 * (141.42vmax - 100%) / 2); 171 | animation-name: background-rotate-animation; 172 | animation-iteration-count: infinite; 173 | 174 | @at-root { 175 | @keyframes background-rotate-animation { 176 | from { 177 | transform: rotate(0deg); 178 | } 179 | to { 180 | transform: rotate(360deg); 181 | } 182 | } 183 | } 184 | } 185 | 186 | &.paused { 187 | animation-play-state: paused; 188 | } 189 | } 190 | 191 | .background-image { 192 | width: 100%; 193 | height: 100%; 194 | background-color: black; 195 | background-size: cover; 196 | background-position: center; 197 | } 198 | 199 | .tracks-container { 200 | height: 100%; 201 | position: relative; 202 | overflow-y: auto; 203 | } 204 | 205 | .tracks { 206 | position: absolute; 207 | top: 0; 208 | left: 0; 209 | z-index: 0; 210 | 211 | display: flex; 212 | flex-wrap: wrap; 213 | justify-content: center; 214 | 215 | box-sizing: border-box; 216 | } 217 | 218 | .backdrop { 219 | position: sticky; 220 | left: 0; 221 | top: 0; 222 | 223 | width: 100%; 224 | height: 100%; 225 | 226 | background: rgba(0, 0, 0, 0.5); 227 | cursor: pointer; 228 | } 229 | 230 | .lyric { 231 | width: 100%; 232 | height: 60px; 233 | position: relative; 234 | 235 | display: flex; 236 | 237 | background: rgba(255, 255, 255, 0.8); 238 | color: #333; 239 | font-size: 36px; 240 | } 241 | 242 | .character { 243 | height: 100%; 244 | width: 160px; 245 | position: relative; 246 | } 247 | 248 | .character-image { 249 | position: absolute; 250 | bottom: 0; 251 | 252 | transition: opacity 0.2s; 253 | pointer-events: none; 254 | 255 | &.disabled { 256 | opacity: 0.7; 257 | } 258 | } 259 | 260 | .lyric-text { 261 | line-height: 60px; 262 | flex: 1 0 0; 263 | 264 | @media (max-width: 600px) { 265 | font-size: 0.5em; 266 | line-height: 1.5em; 267 | padding: 0.3em 0; 268 | } 269 | } 270 | 271 | .lyric-controls { 272 | flex: 0 0 auto; 273 | display: flex; 274 | margin-right: 10px; 275 | } 276 | 277 | .change { 278 | padding: 3px; 279 | 280 | border-radius: 9999px; 281 | 282 | color: white; 283 | font-weight: normal; 284 | 285 | cursor: pointer; 286 | 287 | .character & { 288 | position: absolute; 289 | bottom: 0.5em; 290 | left: 50%; 291 | transform: translateX(-50%); 292 | 293 | background: #2196f3; 294 | font-size: 14px; 295 | } 296 | 297 | .title & { 298 | display: inline; 299 | margin-left: 0.5em; 300 | 301 | background: #555; 302 | font-size: 12px; 303 | } 304 | } 305 | 306 | .background-info { 307 | position: absolute; 308 | right: 1.5em; 309 | bottom: 100%; 310 | 311 | font-family: sans-serif; 312 | font-size: 12px; 313 | font-weight: bold; 314 | color: white; 315 | text-shadow: 0 0 3px black; 316 | 317 | a { 318 | color: #81d4fa; 319 | text-decoration: none; 320 | } 321 | } 322 | 323 | .controls { 324 | flex: 0 0 40px; 325 | 326 | height: 40px; 327 | padding: 0 5px; 328 | 329 | display: flex; 330 | 331 | background: #111; 332 | 333 | color: white; 334 | font-size: 24px; 335 | line-height: 40px; 336 | z-index: 0; 337 | } 338 | 339 | .playback { 340 | display: flex; 341 | } 342 | 343 | .button { 344 | height: 40px; 345 | width: 40px; 346 | color: white; 347 | text-align: center; 348 | cursor: pointer; 349 | 350 | &:hover { 351 | background: rgba(255, 255, 255, 0.3); 352 | } 353 | } 354 | 355 | .title { 356 | flex: 1 0 0; 357 | font-size: 14px; 358 | padding-left: 1em; 359 | overflow-x: auto; 360 | } 361 | 362 | .share { 363 | width: 20em; 364 | padding: 20px 0; 365 | } 366 | 367 | .head { 368 | font-size: 20px; 369 | 370 | &:not(:first-child) { 371 | margin-top: 1em; 372 | } 373 | 374 | strong { 375 | color: #ff9800; 376 | } 377 | } 378 | 379 | .share-icons { 380 | display: flex; 381 | justify-content: center; 382 | } 383 | 384 | .share-icon { 385 | width: 50px; 386 | height: 50px; 387 | font-size: 50px; 388 | cursor: pointer; 389 | 390 | display: flex; 391 | justify-content: center; 392 | align-items: center; 393 | position: relative; 394 | 395 | margin: 0 10px; 396 | 397 | &::before { 398 | content: ''; 399 | 400 | position: absolute; 401 | top: 50%; 402 | left: 50%; 403 | transform: translate(-50%, -50%); 404 | 405 | width: 40px; 406 | height: 40px; 407 | background: white; 408 | border-radius: 10px; 409 | z-index: -1; 410 | } 411 | 412 | &.twitter { 413 | color: #00aced; 414 | } 415 | 416 | &.facebook { 417 | color: #3b5998; 418 | } 419 | 420 | svg { 421 | width: 48px; 422 | height: 48px; 423 | vertical-align: middle; 424 | } 425 | 426 | &.hatena svg { 427 | width: 42px; 428 | height: 42px; 429 | } 430 | } 431 | 432 | .share-name { 433 | font-size: 12px; 434 | 435 | input { 436 | font-size: 12px; 437 | width: 10em; 438 | } 439 | } 440 | 441 | .play-video { 442 | cursor: pointer; 443 | padding: 0 0.2em; 444 | 445 | @media (max-width: 600px) { 446 | display: none; 447 | } 448 | 449 | &:hover { 450 | background: rgba(255, 255, 255, 0.3); 451 | } 452 | 453 | &.active { 454 | color: #f44336; 455 | } 456 | } 457 | 458 | .github { 459 | font-size: 30px; 460 | } 461 | 462 | .unimplemented { 463 | opacity: 0.2; 464 | cursor: not-allowed; 465 | } 466 | 467 | .tooltip { 468 | width: 100%; 469 | height: 100%; 470 | display: block; 471 | } 472 | -------------------------------------------------------------------------------- /src/Loading.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-implicit-coercion */ 2 | 3 | const React = require('react'); 4 | const PropTypes = require('prop-types'); 5 | const classNames = require('classnames'); 6 | const sum = require('lodash/sum'); 7 | const {getResourceUrl} = require('./util.js'); 8 | 9 | import './Loading.pcss'; 10 | import {FaSpinner} from 'react-icons/fa'; 11 | import {MdVolumeUp} from 'react-icons/md'; 12 | 13 | const R = 'right'; 14 | const L = 'left'; 15 | 16 | const progressPositions = [ 17 | // [(R|L), x, y] 18 | [R, 0, 0], 19 | [L, 0, 0], 20 | [R, 0.5, 1], 21 | [L, 0.5, 1], 22 | [R, 1.8, 2], 23 | [L, 1.8, 2], 24 | [R, 1, 0], 25 | [L, 1, 0], 26 | [R, 1.5, 1], 27 | [L, 1.5, 1], 28 | [R, 2.8, 2], 29 | [L, 2.8, 2], 30 | [R, 2, 0], 31 | [L, 2, 0], 32 | [R, 2.5, 1], 33 | [L, 2.5, 1], 34 | [R, 3.8, 2], 35 | [L, 3.8, 2], 36 | [R, 4.8, 2], 37 | [L, 4.8, 2], 38 | ]; 39 | 40 | const width = 25; 41 | const height = 20; 42 | const margin = 10; 43 | 44 | module.exports = class Loading extends React.Component { 45 | static propTypes = { 46 | titleComponents: PropTypes.arrayOf(PropTypes.string.isRequired).isRequired, 47 | transcriber: PropTypes.string, 48 | name: PropTypes.string.isRequired, 49 | statuses: PropTypes.arrayOf( 50 | PropTypes.oneOf(['loading', 'seeking', 'ready']).isRequired 51 | ).isRequired, 52 | vanishing: PropTypes.bool.isRequired, 53 | isPlayReady: PropTypes.bool.isRequired, 54 | onClickOk: PropTypes.func.isRequired, 55 | }; 56 | 57 | static defaultProps = { 58 | transcriber: null, 59 | }; 60 | 61 | constructor(props, state) { 62 | super(props, state); 63 | this.state = { 64 | vanished: false, 65 | }; 66 | } 67 | 68 | getProgress = () => sum( 69 | this.props.statuses.map( 70 | (status) => ({ 71 | loading: 0, 72 | seeking: 1, 73 | ready: 2, 74 | }[status]) 75 | ) 76 | ) / 77 | (this.props.statuses.length * 2); 78 | 79 | handleRef = (root) => { 80 | this.root = root; 81 | }; 82 | 83 | handleTransitionEnd = (event) => { 84 | if (event.target === this.root) { 85 | this.setState({vanished: true}); 86 | } 87 | }; 88 | 89 | handleClickOk = () => { 90 | this.props.onClickOk(); 91 | }; 92 | 93 | render() { 94 | return ( 95 | !this.state.vanished && ( 96 |
101 |
102 |
103 | 107 | {this.props.statuses.map((status, index) => { 108 | const [rightOrLeft, x, y] = progressPositions[index]; 109 | 110 | if (rightOrLeft !== L) { 111 | return null; 112 | } 113 | 114 | return ( 115 | 132 | ); 133 | })} 134 | 135 | 139 | 143 | {this.props.statuses.map((status, index) => { 144 | const [rightOrLeft, x, y] = progressPositions[index]; 145 | 146 | if (rightOrLeft !== R) { 147 | return null; 148 | } 149 | 150 | return ( 151 | 169 | ); 170 | })} 171 | 172 |
173 |
174 | {this.props.titleComponents.map((component, index) => [ 175 | component, 176 | ...(this.props.titleComponents.length - 1 === index 177 | ? [] 178 | : []), 179 | ])} 180 |
181 | {this.props.transcriber && ( 182 |
183 | {this.props.transcriber}さんによるアレンジ 184 |
185 | )} 186 |
~原曲不使用音声による音MAD自動演奏~
187 |
188 | {this.getProgress() === 1 ? ( 189 | 'Completed!' 190 | ) : ( 191 | 192 |
193 | 194 |
{' '} 195 | {Math.floor(this.getProgress() * 100)}% Loaded... 196 |
197 | )} 198 |
199 |
200 | {!this.props.isPlayReady && 201 | this.props.statuses.every((status) => status !== 'loading') && ( 202 |
203 |
204 |
205 | 音量注意! 206 |
207 |
208 | このページは 209 | 210 | 音楽を 211 | 212 | 自動演奏する 213 | 214 | サイトです。 215 | 216 | 音量に 217 | 218 | 注意して 219 | 220 | お楽しみください。 221 |
222 |
223 | OK 224 |
225 |
226 |
227 | )} 228 |
229 | ) 230 | ); 231 | } 232 | }; 233 | -------------------------------------------------------------------------------- /src/Loading.pcss: -------------------------------------------------------------------------------- 1 | .loading { 2 | position: absolute; 3 | top: 0; 4 | left: 0; 5 | right: 0; 6 | bottom: 0; 7 | 8 | background: rgba(0, 0, 0, 0.95); 9 | color: white; 10 | text-align: center; 11 | 12 | z-index: 1; 13 | opacity: 1; 14 | transition: opacity 2s linear; 15 | 16 | &.vanishing { 17 | opacity: 0; 18 | pointer-events: none; 19 | } 20 | } 21 | 22 | .inner { 23 | position: absolute; 24 | top: 50%; 25 | transform: translateY(-50%); 26 | width: 100%; 27 | } 28 | 29 | .progress-area { 30 | display: flex; 31 | justify-content: center; 32 | margin-bottom: 32px; 33 | 34 | height: 128px; 35 | max-height: 30vmin; 36 | } 37 | 38 | .icon { 39 | height: 100%; 40 | } 41 | 42 | .progress { 43 | height: 100%; 44 | width: 200px; 45 | vertical-align: bottom; 46 | } 47 | 48 | .progress-unit { 49 | transition: fill 0.3s; 50 | } 51 | 52 | .title { 53 | font-size: 8vmin; 54 | white-space: pre; 55 | margin-bottom: 10px; 56 | } 57 | 58 | .transcriber { 59 | display: inline-block; 60 | padding: 0 1em; 61 | margin-bottom: 6vmin; 62 | 63 | background: #9c27b0; 64 | 65 | font-size: 3vmin; 66 | font-family: sans-serif; 67 | color: white; 68 | } 69 | 70 | .artist { 71 | font-size: 3vmin; 72 | } 73 | 74 | .loading-text { 75 | font-size: 3vmin; 76 | margin-top: 6vmin; 77 | } 78 | 79 | .spinner { 80 | display: inline-block; 81 | animation-name: spinner-animation; 82 | animation-timing-function: linear; 83 | animation-duration: 0.5s; 84 | animation-iteration-count: infinite; 85 | 86 | @at-root { 87 | @keyframes spinner-animation { 88 | from { 89 | transform: rotate(0deg); 90 | } 91 | to { 92 | transform: rotate(360deg); 93 | } 94 | } 95 | } 96 | } 97 | 98 | .notice-area { 99 | position: absolute; 100 | top: 0; 101 | left: 0; 102 | right: 0; 103 | bottom: 0; 104 | 105 | cursor: pointer; 106 | } 107 | 108 | .notice { 109 | position: absolute; 110 | top: 50%; 111 | left: 20px; 112 | transform: translateY(-50%); 113 | width: calc(100% - 40px); 114 | 115 | background: #555; 116 | border-radius: 5px; 117 | padding: 3vmin 0; 118 | box-sizing: border-box; 119 | 120 | color: white; 121 | } 122 | 123 | .head { 124 | font-size: 10vmin; 125 | line-height: 1.5em; 126 | padding-top: 0.1em; 127 | } 128 | 129 | .body { 130 | margin: 0.5em 1em; 131 | 132 | font-family: sans-serif; 133 | font-size: 5vmin; 134 | text-align: left; 135 | white-space: nowrap; 136 | } 137 | 138 | .ok { 139 | display: inline-block; 140 | padding: 0 2em; 141 | border-radius: 5px; 142 | 143 | background: #388e3c; 144 | 145 | font-size: 7vmin; 146 | font-family: sans-serif; 147 | line-height: 1.5em; 148 | cursor: pointer; 149 | } 150 | -------------------------------------------------------------------------------- /src/SoundSelect.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-implicit-coercion */ 2 | 3 | const assert = require('assert'); 4 | const React = require('react'); 5 | const PropTypes = require('prop-types'); 6 | const classNames = require('classnames'); 7 | const {default: Player} = require('react-player'); 8 | const {Howl} = require('howler'); 9 | 10 | const soundData = require('../sound/data.yml'); 11 | const {getSoundUrls, wait} = require('./util.js'); 12 | 13 | import './SoundSelect.pcss'; 14 | 15 | const getThumbnailUrl = (url) => { 16 | let matches = null; 17 | 18 | matches = url.match(/^https?:\/\/www\.youtube\.com\/watch\?v=(.+)$/); 19 | if (matches) { 20 | return `https://i.ytimg.com/vi/${matches[1]}/1.jpg`; 21 | } 22 | 23 | return 'https://placehold.it/120x90'; 24 | }; 25 | 26 | class Sound extends React.Component { 27 | static propTypes = { 28 | active: PropTypes.bool.isRequired, 29 | name: PropTypes.string.isRequired, 30 | videoUrl: PropTypes.string.isRequired, 31 | resourceWork: PropTypes.string.isRequired, 32 | resourceName: PropTypes.string.isRequired, 33 | onClick: PropTypes.func.isRequired, 34 | onRefActiveSound: PropTypes.func.isRequired, 35 | }; 36 | 37 | handleClick = (event) => { 38 | this.props.onClick(event, this.props.name); 39 | }; 40 | 41 | handleRef = (event) => { 42 | if (this.props.active) { 43 | this.props.onRefActiveSound(event); 44 | } 45 | }; 46 | 47 | render() { 48 | return ( 49 |
54 | 55 |
56 | {this.props.resourceWork} 57 | {'より'} 58 | {this.props.resourceName} 59 |
60 |
61 | ); 62 | } 63 | } 64 | 65 | class Tab extends React.Component { 66 | static propTypes = { 67 | mode: PropTypes.string.isRequired, 68 | name: PropTypes.string.isRequired, 69 | children: PropTypes.oneOfType([ 70 | PropTypes.arrayOf(PropTypes.node), 71 | PropTypes.node, 72 | ]).isRequired, 73 | onClick: PropTypes.func.isRequired, 74 | }; 75 | 76 | handleClick = (event) => { 77 | this.props.onClick(event, this.props.name); 78 | }; 79 | 80 | render() { 81 | return ( 82 |
88 | {this.props.children} 89 |
90 | ); 91 | } 92 | } 93 | 94 | module.exports = class SoundSelect extends React.Component { 95 | static propTypes = { 96 | top: PropTypes.number.isRequired, 97 | left: PropTypes.number.isRequired, 98 | sound: PropTypes.string.isRequired, 99 | type: PropTypes.string.isRequired, 100 | category: PropTypes.string.isRequired, 101 | onSelect: PropTypes.func.isRequired, 102 | }; 103 | 104 | constructor(props, state) { 105 | super(props, state); 106 | 107 | this.direction = this.props.top > 500 ? 'top' : 'bottom'; 108 | 109 | this.updateSound(this.props.sound); 110 | console.log(this.props.category, soundData[this.props.sound].category); 111 | 112 | this.state = { 113 | selectedSound: this.props.sound, 114 | mode: 115 | this.props.category === soundData[this.props.sound].category 116 | ? 'recommended' 117 | : 'all', 118 | isPlaying: true, 119 | }; 120 | 121 | this.playerState = 'loading'; 122 | this.hasScrolled = false; 123 | } 124 | 125 | get soundData() { 126 | return soundData[this.state.selectedSound]; 127 | } 128 | 129 | updateSound = (name) => { 130 | this.sound = new Howl({ 131 | src: getSoundUrls(name), 132 | preload: true, 133 | onend: this.handleSoundEnd, 134 | }); 135 | }; 136 | 137 | updatePlaybackQuality = () => { 138 | if (this.player) { 139 | const internalPlayer = this.player.getInternalPlayer(); 140 | if (internalPlayer && internalPlayer.setPlaybackQuality) { 141 | internalPlayer.setPlaybackQuality('tiny'); 142 | } 143 | } 144 | }; 145 | 146 | handlePlayerReady = () => { 147 | this.playerState = 'ready'; 148 | 149 | this.updatePlaybackQuality(); 150 | this.player.seekTo(this.soundData.video.start); 151 | }; 152 | 153 | handlePlayerPlay = () => { 154 | this.playerState = 'start'; 155 | 156 | this.sound.stop(); 157 | this.sound.play(); 158 | 159 | const session = Symbol('soundPlaySession'); 160 | this.soundPlaySession = session; 161 | 162 | wait(this.soundData.video.duration * 1000).then(() => { 163 | if (this.soundPlaySession !== session) { 164 | return; 165 | } 166 | 167 | this.sound.stop(); 168 | this.setState({isPlaying: false}); 169 | }); 170 | }; 171 | 172 | handleSoundEnd = () => { 173 | this.setState({isPlaying: false}); 174 | }; 175 | 176 | handleClickSound = (event, name) => { 177 | this.sound.stop(); 178 | 179 | if (name === this.state.selectedSound) { 180 | if (this.playerState !== 'start') { 181 | return; 182 | } 183 | 184 | this.player.seekTo(this.soundData.video.start); 185 | this.setState({isPlaying: true}); 186 | } else { 187 | assert(name !== this.state.selectedSound); 188 | 189 | this.updateSound(name); 190 | 191 | this.setState({ 192 | selectedSound: name, 193 | isPlaying: true, 194 | }); 195 | 196 | if (soundData[name].video.url === this.soundData.video.url) { 197 | this.player.seekTo(soundData[name].video.start); 198 | } else { 199 | this.playerStatus = 'loading'; 200 | } 201 | 202 | this.props.onSelect(name); 203 | } 204 | }; 205 | 206 | handleClickTab = (event, mode) => { 207 | if (this.state.mode !== mode) { 208 | this.setState({mode}); 209 | } 210 | }; 211 | 212 | handleRefSounds = (node) => { 213 | if (!node) { 214 | return; 215 | } 216 | 217 | this.soundsNode = node; 218 | this.scrollToActiveSound(); 219 | }; 220 | 221 | handleRefActiveSound = (node) => { 222 | if (!node) { 223 | return; 224 | } 225 | 226 | this.activeSoundOffsetTop = node.offsetTop; 227 | this.scrollToActiveSound(); 228 | }; 229 | 230 | scrollToActiveSound = () => { 231 | if (!this.hasScrolled && this.soundsNode) { 232 | this.soundsNode.scrollTop = this.activeSoundOffsetTop - 20; 233 | this.hasScrolled = true; 234 | } 235 | }; 236 | 237 | render() { 238 | return ( 239 |
246 |
253 |
254 | { 256 | this.player = element; 257 | this.updatePlaybackQuality(); 258 | }} 259 | url={this.soundData.video.url} 260 | config={{ 261 | youtube: { 262 | playerVars: { 263 | start: Math.floor(this.soundData.video.start), 264 | end: Math.ceil( 265 | this.soundData.video.start + this.soundData.video.duration 266 | ), 267 | }, 268 | }, 269 | }} 270 | width={256} 271 | height={144} 272 | playing={this.state.isPlaying} 273 | controls 274 | muted 275 | onReady={this.handlePlayerReady} 276 | onPlay={this.handlePlayerPlay} 277 | /> 278 |
279 |
280 | 285 | おすすめ 286 | 287 | 292 | 全部 293 | 294 |
295 |
296 | {Object.entries(soundData) 297 | .filter(([, sound]) => { 298 | if (this.props.type === 'percussion') { 299 | return sound.type === 'percussion'; 300 | } 301 | 302 | if (this.props.type === 'rap') { 303 | return sound.type === 'rap'; 304 | } 305 | 306 | return sound.type === 'instrument'; 307 | }) 308 | .filter( 309 | ([, sound]) => this.state.mode === 'all' || 310 | sound.category === this.props.category 311 | ) 312 | .map(([name, sound]) => ( 313 | 323 | ))} 324 |
325 |
326 |
327 | ); 328 | } 329 | }; 330 | -------------------------------------------------------------------------------- /src/SoundSelect.pcss: -------------------------------------------------------------------------------- 1 | .sound-select { 2 | position: absolute; 3 | } 4 | 5 | .content { 6 | position: absolute; 7 | 8 | background: white; 9 | width: 300px; 10 | height: 460px; 11 | 12 | border-radius: 5px; 13 | 14 | padding: 10px; 15 | 16 | display: flex; 17 | flex-direction: column; 18 | 19 | $triangle-size: 5px; 20 | 21 | &::before { 22 | content: ''; 23 | position: absolute; 24 | } 25 | 26 | .top & { 27 | bottom: 20px; 28 | right: -30px; 29 | 30 | &::before { 31 | border-right: $triangle-size solid transparent; 32 | border-left: $triangle-size solid transparent; 33 | border-top: $triangle-size solid white; 34 | 35 | top: 100%; 36 | right: calc(30px - $triangle-size); 37 | } 38 | } 39 | 40 | .bottom & { 41 | top: 20px; 42 | right: -30px; 43 | 44 | &::before { 45 | border-right: $triangle-size solid transparent; 46 | border-left: $triangle-size solid transparent; 47 | border-bottom: $triangle-size solid white; 48 | 49 | bottom: 100%; 50 | right: calc(30px - $triangle-size); 51 | } 52 | } 53 | } 54 | 55 | .preview { 56 | padding: 5px; 57 | display: flex; 58 | justify-content: center; 59 | } 60 | 61 | .tabs { 62 | display: flex; 63 | } 64 | 65 | .tab { 66 | $height: 18px; 67 | 68 | height: $height; 69 | line-height: $height; 70 | position: relative; 71 | 72 | background: #9e9e9e; 73 | font-size: 12px; 74 | color: white; 75 | 76 | cursor: pointer; 77 | 78 | $size: 10px; 79 | margin-left: $size; 80 | padding: 0 0.5em; 81 | 82 | &::before { 83 | content: ''; 84 | 85 | position: absolute; 86 | right: 100%; 87 | top: 0; 88 | border-bottom: $height solid #9e9e9e; 89 | border-left: $size solid transparent; 90 | } 91 | 92 | &::after { 93 | content: ''; 94 | 95 | position: absolute; 96 | left: 100%; 97 | top: 0; 98 | border-bottom: $height solid #9e9e9e; 99 | border-right: $size solid transparent; 100 | } 101 | 102 | &.active { 103 | background: #ff5722; 104 | z-index: 1; 105 | 106 | &::before { 107 | border-bottom-color: #ff5722; 108 | } 109 | 110 | &::after { 111 | border-bottom-color: #ff5722; 112 | } 113 | } 114 | } 115 | 116 | .sounds { 117 | flex: 1 0 0; 118 | overflow-y: auto; 119 | user-select: none; 120 | position: relative; 121 | 122 | .active { 123 | background: #d4ecff; 124 | } 125 | } 126 | 127 | .sound { 128 | display: flex; 129 | align-items: center; 130 | padding: 4px 0; 131 | cursor: pointer; 132 | 133 | border-top: 1px solid #dee2e6; 134 | } 135 | 136 | .thumbnail { 137 | max-width: 48px; 138 | max-height: 48px; 139 | margin-right: 8px; 140 | } 141 | 142 | .description { 143 | font-family: sans-serif; 144 | font-size: 12px; 145 | } 146 | -------------------------------------------------------------------------------- /src/Tooltip.css: -------------------------------------------------------------------------------- 1 | .tippy-popper { 2 | font-family: sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /src/Tooltip.jsx: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const PropTypes = require('prop-types'); 3 | const {Tooltip: Tippy} = require('react-tippy'); 4 | 5 | require('./Tooltip.css'); 6 | 7 | const Tooltip = (props) => ( 8 | 9 | {props.children} 10 | 11 | ); 12 | 13 | Tooltip.propTypes = { 14 | children: PropTypes.oneOfType([ 15 | PropTypes.arrayOf(PropTypes.node), 16 | PropTypes.node, 17 | ]).isRequired, 18 | // eslint-disable-next-line react/forbid-prop-types 19 | style: PropTypes.object, 20 | duration: PropTypes.number, 21 | }; 22 | 23 | Tooltip.defaultProps = { 24 | style: {}, 25 | duration: 100, 26 | }; 27 | 28 | module.exports = Tooltip; 29 | -------------------------------------------------------------------------------- /src/Track.jsx: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const {default: Player} = require('react-player'); 3 | const {Howl} = require('howler'); 4 | const PropTypes = require('prop-types'); 5 | const randomColor = require('randomcolor'); 6 | const classNames = require('classnames'); 7 | const assert = require('assert'); 8 | 9 | const soundData = require('../sound/data.yml'); 10 | const {TICK} = require('./const.js'); 11 | const {getSoundUrls, Deferred} = require('./util.js'); 12 | const params = require('./params.js'); 13 | const VolumeControls = require('./VolumeControls.jsx'); 14 | 15 | import './Track.pcss'; 16 | import {MdRefresh} from 'react-icons/md'; 17 | 18 | module.exports = class Track extends React.Component { 19 | static propTypes = { 20 | name: PropTypes.string.isRequired, 21 | type: PropTypes.oneOf(['percussion', 'instrument', 'chord', 'rap']) 22 | .isRequired, 23 | category: PropTypes.string, 24 | score: PropTypes.array, 25 | meanOfNotes: PropTypes.number, 26 | prank: PropTypes.bool, 27 | start: PropTypes.number, 28 | end: PropTypes.number, 29 | intro: PropTypes.number, 30 | sound: PropTypes.string.isRequired, 31 | volume: PropTypes.number.isRequired, 32 | beat: PropTypes.number.isRequired, 33 | size: PropTypes.string.isRequired, 34 | flashCount: PropTypes.number.isRequired, 35 | clearances: PropTypes.arrayOf(PropTypes.number).isRequired, 36 | onFlash: PropTypes.func.isRequired, 37 | onChangeSolo: PropTypes.func.isRequired, 38 | onChangeStatus: PropTypes.func.isRequired, 39 | onClickChange: PropTypes.func.isRequired, 40 | onUpdate: PropTypes.func.isRequired, 41 | onIntroEnded: PropTypes.func.isRequired, 42 | isReady: PropTypes.bool.isRequired, 43 | isIntro: PropTypes.bool.isRequired, 44 | isPaused: PropTypes.bool.isRequired, 45 | isNoVideo: PropTypes.bool.isRequired, 46 | isNotSolo: PropTypes.bool.isRequired, 47 | isPlayReady: PropTypes.bool.isRequired, 48 | }; 49 | 50 | static defaultProps = { 51 | category: null, 52 | score: null, 53 | meanOfNotes: null, 54 | prank: false, 55 | start: null, 56 | end: null, 57 | intro: false, 58 | }; 59 | 60 | constructor(props, state) { 61 | super(props, state); 62 | 63 | this.state = { 64 | volume: this.props.volume, 65 | isPlaying: true, 66 | isReverse: false, 67 | isShown: true, 68 | isMuted: false, 69 | isSolo: false, 70 | isIntroPlaying: false, 71 | isForcePlaying: false, 72 | }; 73 | 74 | this.currentNoteIndex = null; 75 | this.isError = false; 76 | this.isDebug = Boolean(params.debug); 77 | this.isSoundPaused = new WeakMap(); 78 | this.isVideoPaused = false; 79 | 80 | this.updateSound(this.props.sound); 81 | } 82 | 83 | componentWillReceiveProps(nextProps) { 84 | if (this.props.beat !== nextProps.beat) { 85 | this.handleBeat(nextProps.beat); 86 | } 87 | 88 | if (this.props.isReady === false && nextProps.isReady === true) { 89 | this.player && this.player.seekTo(this.soundData.video.start); 90 | this.setState({isShown: false}); 91 | } 92 | 93 | if ( 94 | this.props.isNotSolo === false && 95 | nextProps.isNotSolo === true && 96 | this.state.isSolo === true 97 | ) { 98 | this.setState({isSolo: false}); 99 | } 100 | 101 | if (this.props.isPaused === false && nextProps.isPaused === true) { 102 | this.handlePause(); 103 | } 104 | 105 | if (this.props.isPaused === true && nextProps.isPaused === false) { 106 | this.handleUnpause(); 107 | } 108 | 109 | if (this.props.sound !== nextProps.sound) { 110 | this.updateSound(nextProps.sound); 111 | } 112 | 113 | if (this.props.volume !== nextProps.volume) { 114 | this.setState({volume: nextProps.volume}); 115 | } 116 | 117 | if (!this.props.isIntro && nextProps.isIntro && this.props.intro) { 118 | this.handleStartIntro(); 119 | } 120 | 121 | if (this.props.flashCount !== nextProps.flashCount) { 122 | this.handleFlash(); 123 | } 124 | } 125 | 126 | componentDidUpdate(prevProps, prevState) { 127 | if ( 128 | this.state.volume !== prevState.volume || 129 | this.state.isMuted !== prevState.isMuted || 130 | this.props.isNotSolo !== prevProps.isNotSolo 131 | ) { 132 | for (const sound of this.sounds) { 133 | sound.volume(this.getVolume()); 134 | } 135 | 136 | this.handleUpdate(); 137 | } 138 | 139 | if (this.state.isSolo !== prevState.isSolo) { 140 | this.handleUpdate(); 141 | } 142 | 143 | if (this.state.isMuted !== prevState.isMuted) { 144 | this.handleUpdate(); 145 | } 146 | } 147 | 148 | get soundData() { 149 | return soundData[this.props.sound]; 150 | } 151 | 152 | updateSound = (sound) => { 153 | this.videoLoadDefer = new Deferred(); 154 | this.audioLoadDefer = new Deferred(); 155 | this.isError = false; 156 | 157 | Promise.all( 158 | Array(this.props.type === 'chord' ? 3 : 1) 159 | .fill() 160 | .map( 161 | () => new Promise((resolve, reject) => { 162 | const howl = new Howl({ 163 | src: getSoundUrls(sound), 164 | volume: this.state.volume, 165 | loop: 166 | this.props.type === 'instrument' || 167 | this.props.type === 'chord' 168 | ? soundData[sound].loop === true 169 | : this.props.type !== 'percussion', 170 | html5: this.props.type === 'rap', 171 | preload: true, 172 | onload: () => { 173 | resolve(howl); 174 | }, 175 | onloaderror: (id, error) => { 176 | reject(error); 177 | }, 178 | }); 179 | }) 180 | ) 181 | ).then((sounds) => { 182 | this.sounds = sounds; 183 | this.audioLoadDefer.resolve(); 184 | }); 185 | 186 | Promise.all([ 187 | ...(this.isDebug ? [] : [this.videoLoadDefer.promise]), 188 | this.audioLoadDefer.promise, 189 | ]).then(() => { 190 | // When playing and url props is updated simultaneously, react-player doesn't seem to stop video properly. 191 | // Is this react-player bug? 192 | if (this.props.isNoVideo && this.player) { 193 | this.player.getInternalPlayer().pauseVideo(); 194 | } 195 | this.props.onChangeStatus(this.props.name, 'ready'); 196 | }); 197 | }; 198 | 199 | updatePlaybackQuality = () => { 200 | if (this.player) { 201 | const internalPlayer = this.player.getInternalPlayer(); 202 | if (internalPlayer && internalPlayer.setPlaybackQuality) { 203 | internalPlayer.setPlaybackQuality('tiny'); 204 | } 205 | } 206 | }; 207 | 208 | handleStartIntro = async () => { 209 | this.player.seekTo(25); 210 | await new Promise((resolve) => this.setState( 211 | { 212 | isIntroPlaying: true, 213 | isForcePlaying: true, 214 | isPlaying: true, 215 | isShown: true, 216 | }, 217 | resolve 218 | )); 219 | await new Promise((resolve) => { 220 | const interval = setInterval(() => { 221 | const seconds = this.player.getCurrentTime(); 222 | if (seconds >= 32) { 223 | clearInterval(interval); 224 | resolve(); 225 | } 226 | }, 100); 227 | }); 228 | await new Promise((resolve) => this.setState( 229 | { 230 | isIntroPlaying: false, 231 | isPlaying: false, 232 | isShown: false, 233 | }, 234 | resolve 235 | )); 236 | this.props.onIntroEnded(); 237 | }; 238 | 239 | handleFlash = () => { 240 | this.setState({ 241 | isForcePlaying: !this.props.isNoVideo, 242 | }); 243 | }; 244 | 245 | handleBeat = (beat) => { 246 | const tick = Math.floor((beat + TICK / 2) / TICK) % 2944; 247 | 248 | if (Math.abs(((beat + TICK) % (TICK * 2944)) - TICK) < TICK / 2) { 249 | this.setState({isShown: false}); 250 | for (const sound of this.sounds) { 251 | sound.stop(); 252 | } 253 | } 254 | 255 | let hidden = false; 256 | 257 | for (const clearance of this.props.clearances) { 258 | if (Math.abs((beat % (TICK * 2944)) - TICK * clearance) < TICK / 2) { 259 | this.setState({isShown: false}); 260 | hidden = true; 261 | } 262 | } 263 | 264 | if (this.props.type === 'percussion') { 265 | const playNoteIndex = this.props.score.findIndex( 266 | (note) => Math.abs(note.time - (beat % (TICK * 2944))) < TICK / 2 && 267 | note.type === 'note' 268 | ); 269 | 270 | if (playNoteIndex === -1) { 271 | return; 272 | } 273 | 274 | this.currentNoteIndex = playNoteIndex; 275 | 276 | this.sounds[0].volume(this.getVolume()); 277 | this.sounds[0].play(); 278 | } else if (this.props.type === 'rap') { 279 | if (this.props.start <= tick && tick < this.props.end) { 280 | if (!this.sounds[0].playing()) { 281 | this.setState({ 282 | isPlaying: true, 283 | isShown: true, 284 | }); 285 | 286 | this.sounds[0].rate(135 / this.soundData.tempo); 287 | this.sounds[0].volume(this.getVolume()); 288 | this.sounds[0].seek(0); 289 | this.sounds[0].play(); 290 | 291 | const session = Symbol('videoPlaySession'); 292 | this.videoPlaySession = session; 293 | 294 | if (!this.props.isNoVideo) { 295 | setTimeout(() => { 296 | this.handleVideoSessionTimeout(session); 297 | }, this.soundData.video.duration * 1000); 298 | } 299 | } 300 | 301 | if ((tick - this.props.start) % (32 * this.props.end) === 0) { 302 | if (!this.props.isNoVideo && this.player) { 303 | this.player.seekTo(this.soundData.video.start); 304 | } 305 | } 306 | 307 | if ((tick - this.props.start) % 4 === 0) { 308 | const playbackTime = this.sounds[0].seek(); 309 | const targetTime = 310 | (((tick - this.props.start) % (32 * this.soundData.duration)) * 311 | TICK * 312 | 135) / 313 | this.soundData.tempo + 314 | TICK; 315 | if (Math.abs(playbackTime + TICK - targetTime) > TICK) { 316 | this.sounds[0].seek(targetTime); 317 | } 318 | } 319 | } else if (this.sounds[0].playing()) { 320 | this.setState({ 321 | isPlaying: false, 322 | isShown: false, 323 | }); 324 | this.sounds[0].stop(); 325 | } 326 | 327 | return; 328 | } else { 329 | const playNoteIndex = this.props.score.findIndex( 330 | (note) => Math.abs(note.time - (beat % (TICK * 2944))) < TICK / 2 && 331 | note.type === 'note' 332 | ); 333 | const playNotes = this.props.score.filter( 334 | (note) => Math.abs(note.time - (beat % (TICK * 2944))) < TICK / 2 && 335 | note.type === 'note' 336 | ); 337 | 338 | if ( 339 | playNotes.length !== 0 || 340 | (this.props.score[this.currentNoteIndex] && 341 | Math.abs( 342 | this.props.score[this.currentNoteIndex].time + 343 | this.props.score[this.currentNoteIndex].duration - 344 | (beat % (TICK * 2944)) 345 | ) < 346 | TICK / 2) 347 | ) { 348 | for (const sound of this.sounds) { 349 | sound.stop(); 350 | } 351 | } 352 | 353 | if (playNotes.length === 0) { 354 | return; 355 | } 356 | 357 | this.currentNoteIndex = playNoteIndex; 358 | 359 | // Select the best octave scale based on meanOfNotes and sourceNote 360 | const noteDifference = 361 | this.props.meanOfNotes - (this.soundData.sourceNote % 12); 362 | const downerOctave = Math.floor(noteDifference / 12); 363 | const upperOctave = Math.ceil(noteDifference / 12); 364 | assert(downerOctave <= upperOctave); 365 | const octave = 366 | noteDifference - downerOctave * 12 > upperOctave * 12 - noteDifference 367 | ? upperOctave 368 | : downerOctave; 369 | 370 | playNotes.forEach((note, index) => { 371 | this.sounds[index].rate( 372 | 2 ** 373 | ((note.noteNumber - 374 | octave * 12 - 375 | (this.soundData.sourceNote % 12)) / 376 | 12) 377 | ); 378 | this.sounds[index].volume(this.getVolume()); 379 | this.sounds[index].play(); 380 | }); 381 | } 382 | 383 | if (this.props.category === 'cymbal') { 384 | this.props.onFlash(); 385 | } 386 | 387 | if (this.player) { 388 | this.player.seekTo(this.soundData.video.start); 389 | } 390 | 391 | if (!this.state.isShown || hidden) { 392 | this.setState({isShown: true}); 393 | } 394 | 395 | if (!this.state.isPlaying) { 396 | this.setState({isPlaying: true}); 397 | } 398 | 399 | if (this.props.prank || this.soundData.prank || this.props.isNoVideo) { 400 | this.setState(({isReverse}) => ({isReverse: !isReverse})); 401 | } 402 | 403 | const session = Symbol('videoPlaySession'); 404 | this.videoPlaySession = session; 405 | 406 | if ( 407 | Number.isFinite(this.soundData.video.duration) && 408 | !this.props.isNoVideo 409 | ) { 410 | setTimeout(() => { 411 | this.handleVideoSessionTimeout(session); 412 | }, this.soundData.video.duration * 1000); 413 | } 414 | }; 415 | 416 | handleUpdate = () => { 417 | this.props.onUpdate(this.props.name, { 418 | sound: this.props.sound, 419 | volume: this.state.volume, 420 | muted: this.state.isMuted, 421 | solo: this.state.isSolo, 422 | pan: 0, 423 | }); 424 | }; 425 | 426 | handlePause = () => { 427 | for (const sound of this.sounds) { 428 | if (sound.playing()) { 429 | sound.pause(); 430 | this.isSoundPaused.set(sound, true); 431 | } else { 432 | this.isSoundPaused.set(sound, false); 433 | } 434 | } 435 | 436 | if (this.state.isPlaying) { 437 | this.isVideoPaused = true; 438 | this.setState({isPlaying: false}); 439 | } else { 440 | this.isVideoPaused = false; 441 | } 442 | }; 443 | 444 | handleUnpause = () => { 445 | for (const sound of this.sounds) { 446 | if (this.isSoundPaused.get(sound)) { 447 | sound.play(); 448 | } 449 | } 450 | 451 | if (this.isVideoPaused) { 452 | this.setState({isPlaying: true}); 453 | } 454 | }; 455 | 456 | getVolume = () => { 457 | if ( 458 | this.state.isMuted || 459 | this.props.isNotSolo || 460 | this.isError || 461 | this.props.isPaused 462 | ) { 463 | return 0; 464 | } 465 | 466 | if (this.props.type === 'rap') { 467 | return this.state.volume; 468 | } 469 | 470 | if (this.currentNoteIndex === null) { 471 | return this.state.volume; 472 | } 473 | 474 | const playNote = this.props.score[this.currentNoteIndex]; 475 | 476 | return (playNote.velocity / 100) * this.state.volume; 477 | }; 478 | 479 | handleVideoSessionTimeout = (session) => { 480 | if (this.videoPlaySession === session && this.state.isPlaying) { 481 | this.setState({isPlaying: false}); 482 | } 483 | }; 484 | 485 | handlePlayerReady = () => { 486 | this.updatePlaybackQuality(); 487 | if (this.props.isPlayReady) { 488 | this.player.seekTo(this.soundData.video.start); 489 | } 490 | 491 | this.props.onChangeStatus(this.props.name, 'seeking'); 492 | }; 493 | 494 | handlePlayerPlay = () => { 495 | if (!this.videoLoadDefer.isResolved) { 496 | this.setState({ 497 | isPlaying: false, 498 | }); 499 | this.player.seekTo(this.soundData.video.start); 500 | this.videoLoadDefer.resolve(); 501 | } 502 | }; 503 | 504 | handlePlayerEnded = (event) => { 505 | if (typeof this.onPlayerEnded === 'function') { 506 | this.onPlayerEnded(event); 507 | } 508 | }; 509 | 510 | handlePlayerError = () => { 511 | this.isError = true; 512 | for (const sound of this.sounds) { 513 | sound.volume(this.getVolume()); 514 | } 515 | 516 | if (!this.videoLoadDefer.isResolved) { 517 | this.videoLoadDefer.resolve(); 518 | } 519 | }; 520 | 521 | handleChangeMuted = (isMuted) => { 522 | this.setState({isMuted}); 523 | }; 524 | 525 | handleChangeVolume = (volume) => { 526 | this.setState({volume}); 527 | }; 528 | 529 | handleChangeSolo = (isSolo) => { 530 | this.setState({isSolo}); 531 | this.props.onChangeSolo(this.props.name, isSolo); 532 | }; 533 | 534 | handleClickChange = (event) => { 535 | if (this.changeNode) { 536 | this.props.onClickChange(this.props.name, this.changeNode, event); 537 | } 538 | }; 539 | 540 | handleChangeRef = (node) => { 541 | this.changeNode = node; 542 | }; 543 | 544 | render() { 545 | return ( 546 |
551 |
552 | {this.props.name} 553 |
558 | かえる 559 |
560 |
561 |
572 | {this.isDebug ? ( 573 | this.props.name.toUpperCase() 574 | ) : ( 575 | { 577 | this.player = element; 578 | this.updatePlaybackQuality(); 579 | }} 580 | url={this.soundData.video.url} 581 | config={{ 582 | youtube: { 583 | playerVars: { 584 | start: Math.floor(this.soundData.video.start), 585 | end: Math.ceil( 586 | this.soundData.video.start + this.soundData.video.duration 587 | ), 588 | modestbranding: 1, 589 | }, 590 | }, 591 | }} 592 | width={{small: 192, normal: 224, large: 288}[this.props.size]} 593 | height={{small: 108, normal: 126, large: 162}[this.props.size]} 594 | playing={ 595 | this.props.isPlayReady && 596 | this.state.isPlaying && 597 | (!this.props.isNoVideo || 598 | !this.props.isReady || 599 | this.state.isIntroPlaying || 600 | this.state.isForcePlaying) 601 | } 602 | controls={this.props.size === 'large'} 603 | muted={!this.state.isIntroPlaying} 604 | loop={!this.state.isIntroPlaying} 605 | onReady={this.handlePlayerReady} 606 | onPlay={this.handlePlayerPlay} 607 | onEnded={this.handlePlayerEnded} 608 | onError={this.handlePlayerError} 609 | /> 610 | )} 611 |
612 | 620 |
621 | ); 622 | } 623 | }; 624 | -------------------------------------------------------------------------------- /src/Track.pcss: -------------------------------------------------------------------------------- 1 | .track { 2 | display: inline-block; 3 | vertical-align: top; 4 | margin: 4px; 5 | background: rgba(255, 255, 255, 0.4); 6 | border-radius: 5px; 7 | transition: opacity 0.2s; 8 | overflow: hidden; 9 | 10 | &.muted { 11 | opacity: 0.5; 12 | } 13 | } 14 | 15 | .name { 16 | display: flex; 17 | align-items: center; 18 | justify-content: space-between; 19 | 20 | height: 26px; 21 | padding: 0 0.5em; 22 | 23 | background: #333; 24 | 25 | color: white; 26 | text-transform: uppercase; 27 | font-size: 14px; 28 | font-family: sans-serif; 29 | letter-spacing: 0.05em; 30 | } 31 | 32 | .change { 33 | padding: 3px; 34 | border-radius: 9999px; 35 | 36 | background: #2196f3; 37 | 38 | color: white; 39 | font-weight: normal; 40 | font-size: 12px; 41 | font-family: misaki; 42 | 43 | cursor: pointer; 44 | } 45 | 46 | .video-area { 47 | color: white; 48 | 49 | display: flex; 50 | align-items: center; 51 | justify-content: center; 52 | text-align: center; 53 | 54 | font-size: 48px; 55 | font-weight: bold; 56 | 57 | &.large { 58 | width: 288px; 59 | height: 162px; 60 | } 61 | 62 | &.normal { 63 | width: 224px; 64 | height: 126px; 65 | } 66 | 67 | &.small { 68 | width: 192px; 69 | height: 108px; 70 | } 71 | } 72 | 73 | .controls { 74 | padding: 3px; 75 | display: flex; 76 | align-items: center; 77 | font-size: 20px; 78 | } 79 | 80 | .mute { 81 | color: #333; 82 | cursor: pointer; 83 | } 84 | 85 | .volume { 86 | display: flex; 87 | } 88 | 89 | .volume-back { 90 | fill: #555; 91 | } 92 | 93 | .volume-color { 94 | fill: #2196f3; 95 | } 96 | 97 | .volume-pinch { 98 | fill: white; 99 | cursor: pointer; 100 | } 101 | -------------------------------------------------------------------------------- /src/VocalManager.js: -------------------------------------------------------------------------------- 1 | const {Howl} = require('howler'); 2 | 3 | const {getSoundUrls} = require('./util.js'); 4 | const {TICK} = require('./const.js'); 5 | 6 | const VoiceManager = class VoiceManager { 7 | static initialize = (vocals, initialVocal) => new Promise((resolve) => { 8 | const voiceManager = new VoiceManager({ 9 | vocals, 10 | initialVocal, 11 | onReady: () => { 12 | resolve(voiceManager); 13 | }, 14 | }); 15 | }); 16 | 17 | constructor({vocals, initialVocal, onReady}) { 18 | this.vocals = vocals; 19 | this.vocalName = initialVocal; 20 | this.onReady = onReady; 21 | this.vocalSounds = new Map(); 22 | this.isSoundPaused = new WeakMap(); 23 | this.volume = 1; 24 | this.isMuted = false; 25 | this.isNotSolo = false; 26 | 27 | // Load first vocal and call onReady after loading 28 | this.isReady = false; 29 | this.loadVocal(); 30 | } 31 | 32 | getResourceName = (source) => `vocal/${this.vocalName}/${source}`; 33 | 34 | loadVocal = () => { 35 | const vocals = this.vocals[this.vocalName]; 36 | const vocal = vocals.find( 37 | (v) => !this.vocalSounds.has(this.getResourceName(v.source)) 38 | ); 39 | 40 | if (!vocal) { 41 | return; 42 | } 43 | 44 | const howl = new Howl({ 45 | src: getSoundUrls(this.getResourceName(vocal.source)), 46 | volume: this.getVolume(), 47 | onload: () => { 48 | if (!this.isReady) { 49 | this.isReady = true; 50 | this.onReady(); 51 | } 52 | 53 | this.loadVocal(); 54 | }, 55 | }); 56 | 57 | this.vocalSounds.set(this.getResourceName(vocal.source), howl); 58 | }; 59 | 60 | onBeat(beat) { 61 | for (const {source, start, end} of this.vocals[this.vocalName]) { 62 | if (this.vocalSounds.has(this.getResourceName(source))) { 63 | const vocalSound = this.vocalSounds.get(this.getResourceName(source)); 64 | 65 | if (beat === start) { 66 | vocalSound.stop(); 67 | vocalSound.seek(0); 68 | vocalSound.play(); 69 | } 70 | 71 | if (beat % 16 === 0 && start <= beat && beat <= end) { 72 | const playbackTime = vocalSound.seek(); 73 | if (Math.abs(playbackTime + start * TICK - beat * TICK) > TICK) { 74 | vocalSound.seek(beat * TICK - start * TICK); 75 | } 76 | } 77 | } 78 | } 79 | } 80 | 81 | pause() { 82 | for (const vocalSound of this.vocalSounds.values()) { 83 | if (vocalSound.playing()) { 84 | vocalSound.pause(); 85 | this.isSoundPaused.set(vocalSound, true); 86 | } else { 87 | this.isSoundPaused.set(vocalSound, false); 88 | } 89 | } 90 | } 91 | 92 | unpause() { 93 | for (const vocalSound of this.vocalSounds.values()) { 94 | if (this.isSoundPaused.get(vocalSound)) { 95 | vocalSound.play(); 96 | } 97 | } 98 | } 99 | 100 | getVolume = () => { 101 | if (this.isMuted || this.isNotSolo) { 102 | return 0; 103 | } 104 | 105 | return this.volume; 106 | }; 107 | 108 | updateVolume = () => { 109 | for (const vocalSound of this.vocalSounds.values()) { 110 | vocalSound.volume(this.getVolume()); 111 | } 112 | }; 113 | 114 | mute() { 115 | this.isMuted = true; 116 | this.updateVolume(); 117 | } 118 | 119 | unmute() { 120 | this.isMuted = false; 121 | this.updateVolume(); 122 | } 123 | 124 | enableNotSolo() { 125 | this.isNotSolo = true; 126 | this.updateVolume(); 127 | } 128 | 129 | disableNotSolo() { 130 | this.isNotSolo = false; 131 | this.updateVolume(); 132 | } 133 | 134 | setVolume(volume) { 135 | this.volume = volume; 136 | this.updateVolume(); 137 | } 138 | }; 139 | 140 | module.exports = VoiceManager; 141 | -------------------------------------------------------------------------------- /src/VolumeControls.jsx: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const PropTypes = require('prop-types'); 3 | const classNames = require('classnames'); 4 | const {default: Hammer} = require('react-hammerjs'); 5 | 6 | import './VolumeControls.pcss'; 7 | import {MdVolumeOff, MdVolumeUp} from 'react-icons/md'; 8 | 9 | module.exports = class Track extends React.Component { 10 | static propTypes = { 11 | volume: PropTypes.number.isRequired, 12 | isMuted: PropTypes.bool.isRequired, 13 | isSolo: PropTypes.bool.isRequired, 14 | onChangeVolume: PropTypes.func.isRequired, 15 | onChangeMuted: PropTypes.func.isRequired, 16 | onChangeSolo: PropTypes.func.isRequired, 17 | }; 18 | 19 | constructor(props, state) { 20 | super(props, state); 21 | 22 | this.state = { 23 | isMuted: this.props.isMuted, 24 | isSolo: this.props.isSolo, 25 | }; 26 | 27 | this.previousVolume = this.props.volume; 28 | } 29 | 30 | componentWillReceiveProps(nextProps) { 31 | if (this.props.isMuted !== nextProps.isMuted) { 32 | this.setState({ 33 | isMuted: nextProps.isMuted, 34 | }); 35 | } 36 | 37 | if (this.props.isSolo !== nextProps.isSolo) { 38 | this.setState({ 39 | isSolo: nextProps.isSolo, 40 | }); 41 | } 42 | } 43 | 44 | handleClickMute = () => { 45 | this.setState(({isMuted}) => { 46 | const newIsMuted = !isMuted; 47 | 48 | this.props.onChangeMuted(newIsMuted); 49 | return {isMuted: newIsMuted}; 50 | }); 51 | }; 52 | 53 | handleClickSolo = () => { 54 | this.setState(({isSolo}) => { 55 | const newIsSolo = !isSolo; 56 | 57 | this.props.onChangeSolo(newIsSolo); 58 | return {isSolo: newIsSolo}; 59 | }); 60 | }; 61 | 62 | handleKnobPan = (event) => { 63 | const newVolume = Math.max( 64 | 0, 65 | Math.min(this.previousVolume + event.deltaX / 100, 1) 66 | ); 67 | this.props.onChangeVolume(newVolume); 68 | 69 | if (event.isFinal) { 70 | this.previousVolume = newVolume; 71 | } 72 | }; 73 | 74 | render() { 75 | return ( 76 |
77 |
78 | {this.state.isMuted ? : } 79 |
80 |
81 | {(() => { 82 | const height = 15; 83 | const width = 100; 84 | 85 | return ( 86 | 87 | 96 | 105 | 106 | 112 | 113 | 114 | ); 115 | })()} 116 |
117 |
121 | SOLO 122 |
123 |
124 | ); 125 | } 126 | }; 127 | -------------------------------------------------------------------------------- /src/VolumeControls.pcss: -------------------------------------------------------------------------------- 1 | .controls { 2 | padding: 3px; 3 | display: flex; 4 | background: rgba(255, 255, 255, 0.6); 5 | align-items: center; 6 | font-size: 20px; 7 | user-select: none; 8 | } 9 | 10 | .mute { 11 | color: #333; 12 | cursor: pointer; 13 | } 14 | 15 | .volume { 16 | display: flex; 17 | } 18 | 19 | .volume-back { 20 | fill: #555; 21 | } 22 | 23 | .volume-color { 24 | fill: #2196f3; 25 | } 26 | 27 | .volume-knob { 28 | fill: white; 29 | cursor: pointer; 30 | } 31 | 32 | .solo { 33 | margin-left: 0.3em; 34 | padding: 0 0.3em; 35 | border-radius: 9999px; 36 | 37 | background: #999; 38 | color: white; 39 | font-weight: bold; 40 | font-size: 12px; 41 | font-family: sans-serif; 42 | 43 | cursor: pointer; 44 | 45 | &.active { 46 | color: white; 47 | background: #f44336; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/const.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | TICK: 60 / 135 / 8, 3 | }; 4 | -------------------------------------------------------------------------------- /src/gist.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | module.exports.post = async ({description, filename, content}) => { 4 | const response = await fetch('https://api.github.com/gists', { 5 | mode: 'cors', 6 | method: 'POST', 7 | body: JSON.stringify({ 8 | description, 9 | public: true, 10 | files: { 11 | [filename]: { 12 | content: JSON.stringify(content, null, ' '), 13 | }, 14 | }, 15 | }), 16 | }); 17 | 18 | const data = await response.json(); 19 | 20 | return data.id; 21 | }; 22 | 23 | module.exports.load = async (id) => { 24 | assert(id.match(/^[\da-f]{20,}$/)); 25 | 26 | const response = await fetch(`https://api.github.com/gists/${id}`, { 27 | mode: 'cors', 28 | method: 'GET', 29 | }); 30 | 31 | const data = await response.json(); 32 | 33 | if (!data.files) { 34 | return null; 35 | } 36 | 37 | const file = Object.values(data.files)[0]; 38 | if (!file) { 39 | return null; 40 | } 41 | 42 | try { 43 | return JSON.parse(file.content); 44 | } catch (e) { 45 | return null; 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /src/params.js: -------------------------------------------------------------------------------- 1 | const qs = require('querystring'); 2 | 3 | module.exports = qs.parse(location.search.slice(1)); 4 | -------------------------------------------------------------------------------- /src/util.js: -------------------------------------------------------------------------------- 1 | const getResourceUrl = (path) => process.env.NODE_ENV === 'production' 2 | ? `https://media.githubusercontent.com/media/hakatashi/iwashi/gh-pages/${path}` 3 | : path; 4 | 5 | module.exports.getResourceUrl = getResourceUrl; 6 | 7 | module.exports.getSoundUrls = (id) => [ 8 | getResourceUrl(`sound/${id}.ogg`), 9 | getResourceUrl(`sound/${id}.wav`), 10 | ]; 11 | 12 | module.exports.Deferred = class Deferred { 13 | constructor() { 14 | this.promise = new Promise((resolve, reject) => { 15 | this.nativeReject = reject; 16 | this.nativeResolve = resolve; 17 | }); 18 | 19 | this.isResolved = false; 20 | this.isRejected = false; 21 | } 22 | 23 | resolve(...args) { 24 | this.nativeResolve(...args); 25 | this.isResolved = true; 26 | } 27 | 28 | reject(...args) { 29 | this.nativeReject(...args); 30 | this.isReject = true; 31 | } 32 | }; 33 | 34 | module.exports.wait = (time) => new Promise((resolve) => { 35 | setTimeout(() => { 36 | resolve(); 37 | }, time); 38 | }); 39 | 40 | module.exports.isAndroid = () => navigator.userAgent.match(/android/i); 41 | 42 | module.exports.isIos = () => navigator.userAgent.match(/(iPhone|iPad|iPod)/i); 43 | 44 | module.exports.isMobile = () => module.exports.isAndroid() || module.exports.isIos(); 45 | 46 | module.exports.median = (values) => { 47 | const sortedValues = values.slice().sort((a, b) => a - b); 48 | const med = Math.floor(sortedValues.length / 2); 49 | 50 | if (values.length % 2 === 0) { 51 | return (sortedValues[med - 1] + sortedValues[med]) / 2; 52 | } 53 | 54 | return sortedValues[med]; 55 | }; 56 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const cssnano = require('cssnano'); 4 | const precss = require('precss'); 5 | const autoprefixer = require('autoprefixer'); 6 | const MinifyPlugin = require('babel-minify-webpack-plugin'); 7 | 8 | module.exports = (env, argv = {}) => { 9 | const browsers = [ 10 | 'last 2 chrome versions', 11 | ...(argv.mode === 'production' 12 | ? ['last 2 firefox versions', 'safari >= 9', 'last 2 edge versions'] 13 | : []), 14 | ]; 15 | 16 | const envConfig = { 17 | targets: { 18 | browsers, 19 | }, 20 | useBuiltIns: 'entry', 21 | shippedProposals: true, 22 | debug: true, 23 | modules: 'commonjs', 24 | corejs: 3, 25 | }; 26 | 27 | return { 28 | entry: './index.babel.js', 29 | mode: argv.mode || 'development', 30 | output: { 31 | path: __dirname, 32 | filename: 'index.js', 33 | }, 34 | devtool: 35 | argv.mode === 'production' 36 | ? false // https://github.com/webpack-contrib/babel-minify-webpack-plugin/issues/68 37 | : 'cheap-module-eval-source-map', 38 | module: { 39 | rules: [ 40 | { 41 | test: /\.jsx?$/, 42 | exclude: /node_modules/, 43 | use: { 44 | loader: 'babel-loader', 45 | options: { 46 | presets: [ 47 | ['@babel/preset-env', envConfig], 48 | '@babel/preset-react', 49 | ], 50 | plugins: [ 51 | [ 52 | 'react-css-modules', 53 | { 54 | filetypes: { 55 | '.pcss': { 56 | syntax: 'postcss', 57 | }, 58 | }, 59 | handleMissingStyleName: 'warn', 60 | generateScopedName: '[name]__[local]--[hash:base64:5]', 61 | }, 62 | ], 63 | '@babel/plugin-proposal-class-properties', 64 | '@babel/plugin-proposal-object-rest-spread', 65 | ], 66 | }, 67 | }, 68 | }, 69 | { 70 | test: /\.svg$/, 71 | use: { 72 | loader: 'babel-loader', 73 | options: { 74 | presets: [ 75 | ['@babel/preset-env', envConfig], 76 | '@babel/preset-react', 77 | ], 78 | plugins: [ 79 | '@hakatashi/babel-plugin-react-svg', 80 | '@babel/plugin-proposal-object-rest-spread', 81 | ], 82 | }, 83 | }, 84 | }, 85 | { 86 | test: /\.pcss$/, 87 | exclude: /node_modules/, 88 | use: [ 89 | 'style-loader', 90 | { 91 | loader: 'css-loader', 92 | options: { 93 | modules: true, 94 | importLoaders: 1, 95 | localIdentName: '[name]__[local]--[hash:base64:5]', 96 | }, 97 | }, 98 | { 99 | loader: 'postcss-loader', 100 | options: { 101 | ident: 'postcss', 102 | plugins: [ 103 | precss(), 104 | ...(argv.mode === 'production' 105 | ? [ 106 | autoprefixer({ 107 | browsers, 108 | }), 109 | cssnano(), 110 | ] 111 | : []), 112 | ], 113 | }, 114 | }, 115 | ], 116 | }, 117 | { 118 | test: /\.css$/, 119 | use: [ 120 | 'style-loader', 121 | 'css-loader', 122 | { 123 | loader: 'postcss-loader', 124 | options: { 125 | ident: 'css', 126 | plugins: [...(argv.mode === 'production' ? [cssnano()] : [])], 127 | }, 128 | }, 129 | ], 130 | }, 131 | { 132 | test: /\.ttf$/, 133 | use: [ 134 | { 135 | loader: 'url-loader', 136 | options: { 137 | limit: Infinity, 138 | mimetype: 'application/font-woff', 139 | }, 140 | }, 141 | { 142 | loader: './lib/fontmin-loader.js', 143 | options: { 144 | text: [ 145 | '♪', 146 | 'イワシがつちからはえてくるんだ', 147 | '/', 148 | 'ころんば', 149 | '~原曲不使用音声による音MAD自動演奏~', 150 | '0123456789% Loaded...', 151 | 'Completed!', 152 | '音量注意!', 153 | 'なんねん まえかの ことでした', 154 | 'だれかが ハサミで', 155 | 'タイムラインを ちょんぎった', 156 | 'そして', 157 | 'あしたと きのうが つながった', 158 | 'あしたの ことは しっている', 159 | 'イワシが つちから はえてくるんだ', 160 | 'えきの ホームに あながあく', 161 | 'すのこが きえるんだ', 162 | 'きのうの きおくは きえたけど', 163 | 'きえたってことも よくわからないんだ', 164 | 'そらの うえから ビルがたつ', 165 | 'めが みえなくなってきた', 166 | 'はな は かれず', 167 | 'とり は とばず ねむる', 168 | 'かぜ は とまり つめたく', 169 | 'つき は みちも かけも せず まわる', 170 | 'いままでと これからが つながって', 171 | 'いちにちを とばして わすれて', 172 | 'すすんでく', 173 | 'ここは', 174 | 'もとには もどらなくなった', 175 | 'おすすめ', 176 | '全部', 177 | '動画ON', 178 | '動画OFF', 179 | 'かえる', 180 | ].join(''), 181 | }, 182 | }, 183 | ], 184 | }, 185 | { 186 | test: /\.txt$/, 187 | exclude: /node_modules/, 188 | use: ['raw-loader'], 189 | }, 190 | { 191 | test: /\.yml$/, 192 | exclude: /node_modules/, 193 | use: ['./lib/yaml-loader.js'], 194 | }, 195 | { 196 | test: /\.modernizrrc\.js$/, 197 | use: ['modernizr-loader'], 198 | }, 199 | ], 200 | }, 201 | node: { 202 | fs: 'empty', 203 | net: 'empty', 204 | tls: 'empty', 205 | }, 206 | plugins: [ 207 | new webpack.DefinePlugin({ 208 | 'process.env.NODE_ENV': JSON.stringify(argv.mode), 209 | }), 210 | ...(argv.mode === 'production' ? [new MinifyPlugin()] : []), 211 | ], 212 | resolve: { 213 | alias: { 214 | modernizr$: path.resolve(__dirname, '.modernizrrc.js'), 215 | }, 216 | }, 217 | }; 218 | }; 219 | --------------------------------------------------------------------------------