🦔

Claude3.5、シンセサイザーつくれてすごい

2024/06/26に公開

タイトル通りです。樋口は音楽ガジェット好きでもあるのですが、Claude3.5のartifacts機能で100和音出せるアンビエントシンセサイザーが5分くらいで作れてしまい驚愕でした。これは普通に既製品を買ったら安いやつでも1万円くらいするクオリティなんじゃないですか? みなさんもぜひプロンプト叩いて作ってみてブラウザ上で演奏してみてください。
https://claude.ai/chat/69bf73c3-e993-4be1-9d51-6225bfba007e

①入力したプロンプト

artifacts機能をオンにした状態で、対話的に以下のようにプロンプトを入力していきました。

プロンプト1:

ブラウザで操作可能なアンビエントシンセサイザーを作成してください。20和音が出せる仕様にしてください。それぞれのオシレーターにボタンをつけて、ボタンを押すと音が出る仕様にしてください。

プロンプト2:

音が出ません。アンビエントシンセサイザーとしてブラウザ操作で音が出るところまで実装してください。

プロンプト3:

和音を100まで増やしてください。また、ボタンに文字は入れなくてよいです。色で区別できるようにするとよいかもしれません。

③こんな感じになったら完成

右側の窓がartifacts機能で出力されてくるブラウザアプリです。右上のタブを「Preview」から「Code」に変更すると、裏側で動いているソースコードも読めます。

ソースコード

完成品のソースコードは以下です。こちらをClaude3.5にコピペしても、artifacts機能で動かせます。

import React, { useState, useCallback, useMemo } from 'react';

const AmbientSynth = () => {
  const [audioContext, setAudioContext] = useState(null);
  const [activeOscillators, setActiveOscillators] = useState({});

  const initializeAudioContext = useCallback(() => {
    if (!audioContext) {
      const context = new (window.AudioContext || window.webkitAudioContext)();
      setAudioContext(context);
    }
  }, [audioContext]);

  const frequencies = useMemo(() => {
    const minFreq = 20; // Hz
    const maxFreq = 20000; // Hz
    return Array.from({ length: 100 }, (_, i) => {
      // 対数スケールで周波数を生成
      return minFreq * Math.pow(maxFreq / minFreq, i / 99);
    });
  }, []);

  const playSound = useCallback((index) => {
    initializeAudioContext();
    if (!audioContext) return;

    if (activeOscillators[index]) {
      activeOscillators[index].stop();
      setActiveOscillators(prev => {
        const newOscillators = { ...prev };
        delete newOscillators[index];
        return newOscillators;
      });
    } else {
      const oscillator = audioContext.createOscillator();
      oscillator.type = 'sine';
      oscillator.frequency.setValueAtTime(frequencies[index], audioContext.currentTime);

      const gainNode = audioContext.createGain();
      gainNode.gain.setValueAtTime(0, audioContext.currentTime);
      gainNode.gain.linearRampToValueAtTime(0.2, audioContext.currentTime + 0.05);

      oscillator.connect(gainNode);
      gainNode.connect(audioContext.destination);

      oscillator.start();
      setActiveOscillators(prev => ({ ...prev, [index]: oscillator }));
    }
  }, [audioContext, activeOscillators, frequencies, initializeAudioContext]);

  const getButtonColor = useCallback((index) => {
    const hue = (index / 100) * 360;
    return `hsl(${hue}, 70%, ${activeOscillators[index] ? '60%' : '85%'})`;
  }, [activeOscillators]);

  return (
    <div className="p-4 bg-gray-100 rounded-lg shadow-md">
      <h1 className="text-2xl font-bold mb-4">100和音アンビエントシンセサイザー</h1>
      <div className="grid grid-cols-10 gap-1">
        {frequencies.map((_, index) => (
          <button
            key={index}
            className="w-8 h-8 rounded-full focus:outline-none transition-colors duration-300"
            style={{ backgroundColor: getButtonColor(index) }}
            onClick={() => playSound(index)}
          />
        ))}
      </div>
    </div>
  );
};

export default AmbientSynth;
Accenture Japan (有志)

Discussion