mirror of
https://github.com/FMS-Cat/condition.git
synced 2025-08-20 04:11:41 +02:00
feature: music is hard
This commit is contained in:
26
src/Music.ts
26
src/Music.ts
@@ -1,14 +1,14 @@
|
|||||||
import { GLCat, GLCatBuffer, GLCatProgram, GLCatTexture, GLCatTransformFeedback } from '@fms-cat/glcat-ts';
|
import { GLCat, GLCatBuffer, GLCatProgram, GLCatTexture, GLCatTransformFeedback } from '@fms-cat/glcat-ts';
|
||||||
import { MUSIC_BPM, MUSIC_BUFFER_LENGTH } from './config';
|
import { MUSIC_AUTOMATON_TEXTURE_HEIGHT, MUSIC_BPM, MUSIC_BUFFER_LENGTH } from './config';
|
||||||
import { Pool } from './utils/Pool';
|
import { Pool } from './utils/Pool';
|
||||||
import musicVert from './shaders/music.vert';
|
import musicVert from './shaders/music.vert';
|
||||||
import { gl, glCat } from './globals/canvas';
|
import { gl, glCat } from './globals/canvas';
|
||||||
import samplesOpus from './samples.opus';
|
import samplesOpus from './samples.opus';
|
||||||
import { randomTextureStatic } from './globals/randomTexture';
|
import { randomTextureStatic } from './globals/randomTexture';
|
||||||
import { auto, automaton } from './globals/automaton';
|
import { automaton } from './globals/automaton';
|
||||||
import { Channel } from '@fms-cat/automaton';
|
import { Channel } from '@fms-cat/automaton';
|
||||||
import { injectCodeToShader } from './utils/injectCodeToShader';
|
import { injectCodeToShader } from './utils/injectCodeToShader';
|
||||||
import { AutomatonWithGUI } from '@fms-cat/automaton-with-gui';
|
import type { AutomatonWithGUI } from '@fms-cat/automaton-with-gui';
|
||||||
|
|
||||||
const discardFrag = '#version 300 es\nvoid main(){discard;}';
|
const discardFrag = '#version 300 es\nvoid main(){discard;}';
|
||||||
|
|
||||||
@@ -31,6 +31,7 @@ export class Music {
|
|||||||
private __samples?: GLCatTexture;
|
private __samples?: GLCatTexture;
|
||||||
private __automatonChannelList: Channel[];
|
private __automatonChannelList: Channel[];
|
||||||
private __automatonDefineString: string;
|
private __automatonDefineString: string;
|
||||||
|
private __arrayAutomaton: Float32Array;
|
||||||
private __textureAutomaton: GLCatTexture;
|
private __textureAutomaton: GLCatTexture;
|
||||||
|
|
||||||
constructor( glCat: GLCat, audio: AudioContext ) {
|
constructor( glCat: GLCat, audio: AudioContext ) {
|
||||||
@@ -51,12 +52,12 @@ export class Music {
|
|||||||
|
|
||||||
this.__bufferTransformFeedbacks[ 0 ].setVertexbuffer(
|
this.__bufferTransformFeedbacks[ 0 ].setVertexbuffer(
|
||||||
MUSIC_BUFFER_LENGTH * 4,
|
MUSIC_BUFFER_LENGTH * 4,
|
||||||
gl.DYNAMIC_COPY
|
gl.STREAM_READ
|
||||||
);
|
);
|
||||||
|
|
||||||
this.__bufferTransformFeedbacks[ 1 ].setVertexbuffer(
|
this.__bufferTransformFeedbacks[ 1 ].setVertexbuffer(
|
||||||
MUSIC_BUFFER_LENGTH * 4,
|
MUSIC_BUFFER_LENGTH * 4,
|
||||||
gl.DYNAMIC_COPY
|
gl.STREAM_READ
|
||||||
);
|
);
|
||||||
|
|
||||||
this.__transformFeedback.bindBuffer( 0, this.__bufferTransformFeedbacks[ 0 ] );
|
this.__transformFeedback.bindBuffer( 0, this.__bufferTransformFeedbacks[ 0 ] );
|
||||||
@@ -68,6 +69,10 @@ export class Music {
|
|||||||
|
|
||||||
this.__updateAutomatonChannelList();
|
this.__updateAutomatonChannelList();
|
||||||
|
|
||||||
|
this.__arrayAutomaton = new Float32Array(
|
||||||
|
MUSIC_BUFFER_LENGTH * MUSIC_AUTOMATON_TEXTURE_HEIGHT
|
||||||
|
);
|
||||||
|
|
||||||
this.__textureAutomaton = glCat.createTexture();
|
this.__textureAutomaton = glCat.createTexture();
|
||||||
this.__textureAutomaton.textureFilter( gl.NEAREST );
|
this.__textureAutomaton.textureFilter( gl.NEAREST );
|
||||||
|
|
||||||
@@ -210,26 +215,25 @@ export class Music {
|
|||||||
if ( channelName.startsWith( 'Music/' ) ) {
|
if ( channelName.startsWith( 'Music/' ) ) {
|
||||||
const key = channelName.substring( 6 );
|
const key = channelName.substring( 6 );
|
||||||
const index = this.__automatonChannelList.length;
|
const index = this.__automatonChannelList.length;
|
||||||
this.__automatonDefineString += `const int AUTO_${key}=${index};`;
|
const y = ( index + 0.5 ) / MUSIC_AUTOMATON_TEXTURE_HEIGHT;
|
||||||
|
this.__automatonDefineString += `const float AUTO_${key}=${y};`;
|
||||||
this.__automatonChannelList.push( channel );
|
this.__automatonChannelList.push( channel );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private __updateAutomatonTexture(): void {
|
private __updateAutomatonTexture(): void {
|
||||||
const buffer = new Float32Array( MUSIC_BUFFER_LENGTH * 256 );
|
|
||||||
|
|
||||||
for ( const [ iChannel, channel ] of this.__automatonChannelList.entries() ) {
|
for ( const [ iChannel, channel ] of this.__automatonChannelList.entries() ) {
|
||||||
for ( let iSample = 0; iSample < MUSIC_BUFFER_LENGTH; iSample ++ ) {
|
for ( let iSample = 0; iSample < MUSIC_BUFFER_LENGTH; iSample ++ ) {
|
||||||
const t = this.time + iSample / this.audio.sampleRate;
|
const t = this.time + iSample / this.audio.sampleRate;
|
||||||
buffer[ MUSIC_BUFFER_LENGTH * iChannel + iSample ] = channel.getValue( t );
|
this.__arrayAutomaton[ MUSIC_BUFFER_LENGTH * iChannel + iSample ] = channel.getValue( t );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.__textureAutomaton.setTextureFromArray(
|
this.__textureAutomaton.setTextureFromArray(
|
||||||
MUSIC_BUFFER_LENGTH,
|
MUSIC_BUFFER_LENGTH,
|
||||||
256,
|
MUSIC_AUTOMATON_TEXTURE_HEIGHT,
|
||||||
buffer,
|
this.__arrayAutomaton,
|
||||||
{
|
{
|
||||||
internalformat: gl.R32F,
|
internalformat: gl.R32F,
|
||||||
format: gl.RED,
|
format: gl.RED,
|
||||||
|
@@ -1 +1,3 @@
|
|||||||
export { sine, hermitePatch } from '@fms-cat/automaton-fxs';
|
export { sine, hermitePatch } from '@fms-cat/automaton-fxs';
|
||||||
|
export { repeat } from './repeat';
|
||||||
|
export { transpose } from './transpose';
|
||||||
|
22
src/automaton-fxs/repeat.ts
Normal file
22
src/automaton-fxs/repeat.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import type { FxDefinition } from '@fms-cat/automaton';
|
||||||
|
|
||||||
|
export const repeat: FxDefinition = {
|
||||||
|
name: 'Repeat',
|
||||||
|
description: 'Repeat a section of the curve.',
|
||||||
|
params: {
|
||||||
|
interval: { name: 'Interval', type: 'float', default: 1.0, min: 0.0 },
|
||||||
|
},
|
||||||
|
func( context ) {
|
||||||
|
if ( context.index === context.i1 ) {
|
||||||
|
context.setShouldNotInterpolate( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
( context.elapsed + context.deltaTime ) % context.params.interval < context.deltaTime
|
||||||
|
) {
|
||||||
|
context.setShouldNotInterpolate( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.getValue( context.t0 + context.elapsed % context.params.interval );
|
||||||
|
}
|
||||||
|
};
|
19
src/automaton-fxs/transpose.ts
Normal file
19
src/automaton-fxs/transpose.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import type { FxDefinition } from '@fms-cat/automaton';
|
||||||
|
|
||||||
|
export const transpose: FxDefinition = {
|
||||||
|
params: {
|
||||||
|
note: { name: 'Note', type: 'float', default: 0.0 }
|
||||||
|
},
|
||||||
|
func( context ) {
|
||||||
|
if ( context.init ) {
|
||||||
|
context.state.v0 = context.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( context.index === context.i1 ) {
|
||||||
|
context.setShouldNotInterpolate( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
const { v0 } = context.state;
|
||||||
|
return v0 + ( context.value - v0 ) * Math.pow( 2.0, context.params.note / 12.0 );
|
||||||
|
}
|
||||||
|
};
|
File diff suppressed because one or more lines are too long
@@ -5,4 +5,5 @@ export const
|
|||||||
AO_RESOLUTION_RATIO = 1.0,
|
AO_RESOLUTION_RATIO = 1.0,
|
||||||
RESOLUTION = [ 1280, 720 ],
|
RESOLUTION = [ 1280, 720 ],
|
||||||
MUSIC_BPM = 180,
|
MUSIC_BPM = 180,
|
||||||
MUSIC_BUFFER_LENGTH = 4096;
|
MUSIC_BUFFER_LENGTH = 4096,
|
||||||
|
MUSIC_AUTOMATON_TEXTURE_HEIGHT = 16;
|
||||||
|
@@ -40,8 +40,8 @@ in float off;
|
|||||||
out float outL;
|
out float outL;
|
||||||
out float outR;
|
out float outR;
|
||||||
|
|
||||||
float auto( int index ) {
|
float auto( float y ) {
|
||||||
return texture( samplerAutomaton, vec2( off / bufferLength, ( float( index ) + 0.5 ) / 256.0 ) ).x;
|
return texture( samplerAutomaton, vec2( off / bufferLength, y ) ).x;
|
||||||
}
|
}
|
||||||
|
|
||||||
float fs( float s ) {
|
float fs( float s ) {
|
||||||
@@ -372,7 +372,6 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
// -- snare --------------------------------------------------------------------------------------
|
// -- snare --------------------------------------------------------------------------------------
|
||||||
if ( inRange( time.w, SECTION_NEURO, SECTION_PORTER_FUCKING_ROBINSON ) ) {
|
if ( inRange( time.w, SECTION_NEURO, SECTION_PORTER_FUCKING_ROBINSON ) ) {
|
||||||
float t = mod( time.y - 2.0 * BEAT, 4.0 * BEAT );
|
float t = mod( time.y - 2.0 * BEAT, 4.0 * BEAT );
|
||||||
// float t = mod( time.z - 2.0 * BEAT, 4.0 * BEAT );
|
|
||||||
dest += 0.12 * snare( t );
|
dest += 0.12 * snare( t );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,7 +390,7 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
|
|
||||||
float tt = t + det * fi * sin( fi * detPhase + 1.0 * t );
|
float tt = t + det * fi * sin( fi * detPhase + 1.0 * t );
|
||||||
|
|
||||||
float radius = 0.2 + 0.1 * wubIntensity * fbm( 0.1 * vec2( tri( n2f( -36.0 ) * wubFreq * tt ) ) ).x;
|
float radius = 0.1 * wubIntensity * fbm( 0.1 * vec2( sin( TAU * n2f( -36.0 ) * wubFreq * tt ) ) ).x;
|
||||||
|
|
||||||
float phase = 0.2 * tri( n2f( -36.0 ) * tt );
|
float phase = 0.2 * tri( n2f( -36.0 ) * tt );
|
||||||
vec2 uv = radius * vec2( sin( phase ), cos( phase ) ) + 0.4;
|
vec2 uv = radius * vec2( sin( phase ), cos( phase ) ) + 0.4;
|
||||||
|
Reference in New Issue
Block a user