Skip to content
This repository has been archived by the owner on Sep 27, 2024. It is now read-only.

Commit

Permalink
Merge pull request #19 from Project-Null-Undefined/issues/#12
Browse files Browse the repository at this point in the history
曲線から音階に分割する処理の完成
  • Loading branch information
SatooRu65536 authored Sep 13, 2024
2 parents f977fa8 + dc0a59e commit 2bd477c
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 7 deletions.
6 changes: 6 additions & 0 deletions src/app/draw/features/FreeDrawing/const/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const BAR_NUM = 8;
export const NOTE_NUM = 4;
export const SCALE_NUM = 7;

export const WHOLE_NOTE = [1, 2, 4, 5, 6];
export const HALF_NOTE = [3, 7];
9 changes: 9 additions & 0 deletions src/app/draw/features/FreeDrawing/dto/curve.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type Coordinate = {
x: number;
y: number;
};

export type CurveInformationDto = {
coordinates: Coordinate[];
length: number;
};
58 changes: 58 additions & 0 deletions src/app/draw/features/FreeDrawing/functions/curveDraw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import paper from 'paper';
import styles from '@/styles/colors.module.scss';
import { Coordinate, CurveInformationDto } from '../dto/curve';

function handleMouseDown(event: paper.ToolEvent): paper.Path {
const newPath = new paper.Path();
newPath.strokeColor = new paper.Color(styles.primaryColor);
newPath.strokeWidth = 2;
newPath.add(event.point);
return newPath;
}

function handleMouseDrag(event: paper.ToolEvent, path: paper.Path | null) {
if (path) {
path.add(event.point);
}
}

async function handleMouseUp(path: paper.Path | null): Promise<CurveInformationDto> {
let curveInformation: CurveInformationDto = { coordinates: [], length: 0 };

if (path) {
path.smooth();
const coordinates: Coordinate[] = path.segments.map((segment: paper.Segment) => ({
x: segment.point.x,
y: segment.point.y,
}));
const length = path.length;

curveInformation = { coordinates, length };
}

return curveInformation;
}

export async function curveDraw(): Promise<CurveInformationDto> {
let path: paper.Path | null = null;
let curveInformation: CurveInformationDto = { coordinates: [], length: 0 };

return new Promise((resolve) => {
const tool = new paper.Tool();

// イベントハンドラの呼び出し
tool.onMouseDown = (event: paper.ToolEvent) => {
path = handleMouseDown(event);
};

tool.onMouseDrag = (event: paper.ToolEvent) => {
handleMouseDrag(event, path);
};

tool.onMouseUp = async () => {
curveInformation = await handleMouseUp(path);

resolve(curveInformation);
};
});
}
11 changes: 11 additions & 0 deletions src/app/draw/features/FreeDrawing/functions/curveSprit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { BAR_NUM, NOTE_NUM } from '../const';
import { Coordinate } from '../dto/curve';

export function splitCurve(coordinates: Coordinate[]): Coordinate[] {
const resultCurve = Array.from(
{ length: BAR_NUM * NOTE_NUM },
(_, i) => coordinates[Math.floor((i * coordinates.length) / (BAR_NUM * NOTE_NUM))],
);

return resultCurve;
}
30 changes: 30 additions & 0 deletions src/app/draw/features/FreeDrawing/functions/intervalCreate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Interval, ScaleInterval } from '@/types';
import { Coordinate } from '../dto/curve';
import { HALF_NOTE, SCALE_NUM, WHOLE_NOTE } from '../const';

export function createInterval(curveCoordinates: Coordinate[]): Interval[] {
const yBase = curveCoordinates[0].y;
const yMax = Math.max(...curveCoordinates.map((c) => c.y - yBase));
const yMin = Math.min(...curveCoordinates.map((c) => c.y - yBase));
const yMaxAbs = Math.max(Math.abs(yMax), Math.abs(yMin));

const normalizedCurve = curveCoordinates.map((c) => ({
x: c.x,
y: Math.abs((c.y - yBase) / yMaxAbs),
}));
const scaledCurveY: ScaleInterval[] = normalizedCurve.map((nc) => {
return Math.floor(nc.y * SCALE_NUM) as ScaleInterval;
});

const interval: Interval[] = scaledCurveY.map((scy) => {
if (WHOLE_NOTE.includes(scy)) {
return 2;
} else if (HALF_NOTE.includes(scy)) {
return 1;
} else {
return 0;
}
});

return interval;
}
20 changes: 14 additions & 6 deletions src/app/draw/features/FreeDrawing/hooks/useDrawing.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import { useEffect, useRef } from 'react';
import paper from 'paper';
import { setupDrawingTool } from '../functions/drawing';
import { curveDraw } from '../functions/curveDraw';
import { splitCurve } from '../functions/curveSprit';
import { createInterval } from '../functions/intervalCreate';

export function useDrawing() {
const canvasRef = useRef<HTMLCanvasElement>(null);

useEffect(() => {
const canvas = canvasRef.current;
if (canvas) {
paper.setup(canvas);
setupDrawingTool();
}
const setupCanvas = async () => {
const canvas = canvasRef.current;
if (canvas) {
paper.setup(canvas);
const curveInformation = await curveDraw();
const curveCoordinates = splitCurve(curveInformation.coordinates);
const interval = createInterval(curveCoordinates);
}
};

setupCanvas();

return () => {
paper.project.clear();
Expand Down
3 changes: 2 additions & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export interface Settings {
}

// 音程 (1音目を0として 全音:2, 半音:1 で表現)
export type Interval = number[];
export type Interval = 0 | 1 | 2;
export type ScaleInterval = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;

// リズム (8小節の場合は length = 8小節 * 4拍 * 4 = 128)
export type Rhythm = Beat[];

0 comments on commit 2bd477c

Please sign in to comment.