3P by GN⁺ | ★ favorite | 댓글 1개
  • 악기와 장비가 없어도 음악을 만들 수 있는 환경으로 Sonic Pi가 소개되며, Ruby 기반 DSL로 음표·코드·스케일·타이밍을 직접 작성할 수 있음
  • Ruby의 함수, 배열, 조건문, 반복, 스코프를 활용하면 play, sleep, play_pattern_timed, chord, scale을 묶어 반복 패턴과 아르페지오를 간결하게 구성 가능함
  • in_thread, ring, flatten, splat 연산자, with_fx를 조합하면 여러 “악기”를 동시에 실행하고 겹친 음과 다른 리듬을 레이어링할 수 있음
  • ADSR 엔벨로프의 attack, decay, sustain, release 조절은 실제 합창 재현보다 유지 시간과 분리감을 맞추는 데 초점이 있음
  • live_loop는 재생 중인 코드를 갱신하며 반복 실행할 수 있어 Sonic Pi를 라이브 퍼포먼스용 도구로 만들고, 코드를 읽히는 텍스트이자 창작 행위로 보게 함

코드로 제어하는 Sonic Pi

  • Sonic Pi는 일반적인 오디오 애플리케이션과 달리 코드로만 제어되는 소프트웨어 신시사이저
  • 자체 제어 언어는 Ruby를 확장한 도메인 특화 언어(DSL) 이며, 음악과 오디오 개념을 Ruby 문법 위에 매핑함
  • 기본 요소는 Ruby 값과 Sonic Pi 함수로 구성됨
    • :c4 같은 음표 이름은 해당 MIDI 코드에 대응하는 심볼로 사용됨
    • chord(:d3, :maj7)처럼 루트 음과 코드 구조를 인자로 받아 코드를 만들 수 있음
    • play는 음을 재생하고, Ruby의 sleep과 함께 시간 간격을 제어함
    • play_pattern_timed는 음 목록과 시간 간격을 받아 반복 재생 코드를 줄여줌
  • 예제의 목표는 외부 MIDI나 샘플 없이 Sonic Pi 기본 기능만으로 데모용 반주를 코드로 만드는 것임
  • Sonic Pi 앱을 설치하면 예제 코드를 붙여 넣어 따라 할 수 있고, 언어 문서와 튜토리얼도 기본 제공됨

Ruby 문법으로 반복 패턴 만들기

  • 기본 예제는 use_bpm 70으로 BPM을 바꾸고, use_synth :pulse로 기본 사인파 대신 pulse 신시사이저를 사용함
  • play :c2, sleep 0.25를 반복하면 음을 순서대로 재생할 수 있으며, play_pattern_timed [ :c3, :d3, :e3, :g3 ], 0.25로 같은 구조를 더 짧게 쓸 수 있음
  • 제어 언어가 Ruby 위에 있으므로 함수와 반복으로 패턴을 추상화할 수 있음
    • arpeggiate 함수는 루트 음과 선택적 단조 여부를 받아 상승·하강 패턴을 만듦
    • 4.times 반복으로 같은 패턴을 여러 옥타브에 걸쳐 실행함
    • 조건문으로 단조일 때 3음을 바꾸고, 배열의 map으로 루트 음에 간격을 더해 음 목록을 생성함
  • use_synth_defaults amp: 0.1처럼 신시사이저 기본 옵션을 먼저 설정할 수 있고, playplay_pattern_timed에 직접 옵션을 넘길 수도 있음
  • Ruby에서는 함수 호출 괄호가 선택적이지만, play chord(:a3, maj7) 같은 경우에는 구분을 명확히 해야 할 수 있음

병렬 실행과 레이어링

  • in_thread do 블록은 Sonic Pi에서 코드를 병렬로 실행하는 데 사용됨
  • 서로 다른 in_thread 블록을 두면 두 개의 별도 “악기”를 동시에 실행할 수 있음
    • 한 스레드는 아르페지오 패턴을 맡을 수 있음
    • 다른 스레드는 use_synth :saw와 멜로디 배열, 리듬 배열을 사용해 별도 선율을 재생할 수 있음
  • play_pattern_timed는 음 목록뿐 아니라 시간 간격 목록도 받을 수 있음
    • [1] * 2[1, 1]처럼 배열 길이를 늘려 내용을 반복함
    • 중첩 배열은 play_pattern_timed가 그대로 받지 않으므로 flatten으로 한 겹의 배열로 펴서 사용함
  • 합창처럼 겹친 음을 만들 때는 ring(:c5, :e5)처럼 여러 음을 함께 묶을 수 있음
  • flattenring 내부 목록까지 합쳐버릴 수 있어, 이 경우에는 splat 연산자 *로 리스트 내용을 부모 배열에 펼치는 방식을 사용함

스코프, 효과, 합창 파트 구성

  • 중첩된 in_thread를 사용하면 바깥 스코프의 리듬 조각을 공유하면서도, 안쪽 스레드마다 같은 변수 이름을 다시 쓸 수 있음
  • 소프라노와 알토 같은 파트를 별도 스레드로 나누면 각 블록이 자기 스코프를 가지므로 서로의 변수에 직접 접근하지 않음
  • with_fx :reverb, mix: 0.2는 효과 블록을 만들며, 신호 흐름은 가장 안쪽 레이어에서 시작해 바깥쪽 효과 체인으로 이동함
  • mix는 wet 신호와 dry 신호의 혼합 정도를 나타냄
    • wet 신호는 효과가 적용된 신호임
    • dry 신호는 효과가 없는 신호임
  • 전체 그룹을 하나의 효과로 감싸는 것은 DAW의 버스와 비슷하게 사용할 수 있지만, 더 깊은 라우팅은 수동적이며 스코프 때문에 대체로 위에서 아래로 구성해야 함
  • Sonic Pi는 정교한 프로덕션 도구라기보다 악기처럼 다루는 편이 자연스러움

ADSR 엔벨로프로 음 길이 맞추기

  • play_pattern_timedsustain 값을 추가하므로, 긴 코드와 짧은 코드의 유지 시간을 직접 맞출 수 있음
  • attack, decay, sustain, release는 음량이 시간에 따라 어떻게 변하는지를 나타내는 ADSR 엔벨로프
    • attack은 0에서 첫 피크까지 도달하는 시간이며, 기타 줄을 튕기거나 피아노 해머가 닿는 순간처럼 초기 타격에 해당함
    • decay는 첫 피크에서 내려오는 시간이며, 피아노 키나 기타 줄을 누르고 있어도 소리가 서서히 줄어드는 구간에 해당함
    • sustain은 안정된 음량으로 소리를 유지하는 시간이며, 활로 켠 현이나 길게 낸 보컬처럼 유지되는 소리에 해당함
    • release는 소리를 놓은 뒤 실제로 조용해질 때까지의 시간임
  • 모든 소리가 ADSR 요소를 모두 갖는 것은 아님
    • 신시사이저 톤은 생성된 음이므로 반드시 초기 빌드업이나 잔향이 있는 것은 아님
    • 자연 악기는 연주 방식에 따라 요소의 비율이 달라짐
  • 예제의 합창 시뮬레이션은 실재감보다 음이 정확한 시간 동안 유지되고 코드 사이에 약간의 분리가 생기도록 하는 데 집중함
  • choral_rings notes, sus 함수는 음 목록과 유지 시간을 받아 ring(*notes)로 함께 재생하고, sustainrelease를 계산한 뒤 sleep sus로 다음 이벤트까지 기다림

live_loop로 라이브 코딩하기

  • live_loop를 사용하면 코드를 무기한 반복 실행할 수 있음
  • Sonic Pi는 라이브 퍼포먼스를 많이 염두에 둔 도구이며, live_loop 안의 코드는 프로그램을 멈출 때까지 실행됨
  • 재생 중에도 루프 내용을 바꿀 수 있고, 시작 명령을 다시 실행하면 다음 반복부터 갱신된 루프가 적용됨
  • 기존의 바깥 in_thread 루프는 live_loop :some_unique_name 형태로 바꿀 수 있음
  • 효과 체인은 루프가 돌 때마다 다시 만들어지므로, 효과를 많이 쌓을수록 live_loop 바깥에 두는 편이 리소스 측면에서 더 저렴함
  • 최종 예제는 live_loop :harplive_loop :choir로 구성됨
    • :harp 루프는 :square 신시사이저와 0.25 길이의 아르페지오 패턴을 사용함
    • :choir 루프는 :saw 신시사이저, sleep 64, with_fx :reverb, mix: 0.75, choral_rings 함수 호출로 합창 코드를 재생함

프로그래밍을 창작 행위로 보기

  • 기술 작업은 보통 컴퓨터 과학의 관점에서 논의되지만, 프로그래밍도 예술이 될 수 있음
  • 오디오 생성이나 CSS 레이아웃처럼 의도적으로 창의적인 결과물을 만들 때만 예술적인 것은 아님
  • 코드는 기계에 최적화된 명령만이 아니라 다른 사람과 미래의 자신이 읽는 조직화된 텍스트
  • 좋은 코드는 다른 사람이나 6개월 뒤의 자신이 한눈에 이해할 수 있도록 쓰인 코드임
  • 때로는 코드의 예술성이 그 자체로 목적이 되며, Sonic Pi 예제는 그 지점을 음악 제작으로 보여줌

댓글과 토론

Hacker News 의견들
  • 라이브 코딩에 관심 있으면 Glicol(https://glicol.org)도 써볼 만함
    TidalCycles도 있고, Haskell과 Ruby가 DSL을 만드는 능력은 정말 칭찬할 만함
    Glicol에서는 신시사이저에서 영감을 받은 문법, 작곡 속도, 사운드 디자인 편의성에 초점을 두고 있음. 기존 프로그래밍 습관을 가져오되 특정 언어에 갇히지 않는 DSL을 설계하려는 발상임

  • 몇 년 전 YouTube에서 누군가 Sonic Pi로 THX Deep Note를 재현하는 영상을 봤음
    처음엔 뭘 만들 건지 설명하지 않고, 소리의 단일 “음”을 만들면서 그걸 벌이라고 불렀음. 그 벌 소리를 조금씩 조정하고 들려준 뒤, 마지막에 “이 벌을 몇백 마리 만들어서 벌집에서 어떻게 들리는지 보자”는 식으로 진행했는데, 그 순간 Deep Note가 나타났음
    그 영상이 정말 좋았는데 이후로 다시 찾지 못했음. 링크를 아는 사람이 있으면 공유해주면 좋겠음

  • Ruby가 빛나는 경우 중 하나라고 봄. 메타프로그래밍 덕분에 문법을 거의 영어처럼 보이게 만들 수 있음

    • 맞지만 Sonic Pi DSL은 자연어 느낌보다는 약간 Lisp에 더 가까운 느낌임
    • 메타프로그래밍이 맞음
  • 몇 년 전 Sam Aaron, 즉 Sonic Pi의 만든 사람이 Sonic Pi로 라이브 공연하는 걸 본 적 있음
    코드가 실시간으로 바뀔 때마다 음악도 계속 진화했고, 실제로 좋았음

    • 나도 Sam을 만난 적 있음. 2008~2010년쯤 Clojure Conj에서 발표한 뒤 같이 저녁을 먹었는데, 그때도 정말 좋은 사람이었고 발표도 훌륭했음
  • Sonic Pi를 쓰는 아티스트 예시가 궁금하면 예전에 DJ_Dave를 알게 됐는데, 재능 있고 숙련된 음악가가 이 도구를 잘 쓰는 좋은 사례라고 봄
    예전에 Reddit에서 AMA도 했고, GitHub에도 작업물이 있는 것 같음
    [1] https://www.youtube.com/watch?v=JiQHclg_648
    [2] https://www.reddit.com/r/audius/comments/19dxmy6/hey_audius_...
    [3] https://github.com/algorave-dave

  • Ruby 개발자로서는 정말 멋져 보임. 알고리즘 생성 음악에 쓰면 재미있을 것 같고, 시끄러운 git 저장소 이벤트를 어떤 알고리즘 음악으로 바꿔보고 싶었는데 여기에 잘 맞아 보임
    하지만 여러 건반 악기를 가진 음악가 입장에서, 곡을 작곡하려면 MIDI 키보드로 연주하거나 어쿠스틱 악기를 녹음해서 루프하면 되는데 굳이 Ruby로 음악 시퀀스를 짤 이유는 잘 모르겠음. Ruby DSL로 원하는 걸 입력할 수 있는 건 알지만, 피아노 건반에 비해 사용자 경험이 좋다고 하긴 어려움
    다시 말하면 Logic을 대체하려고 이걸 쓰지는 않을 것 같음. 물론 개인적인 취향임
    참고: http://listen.hatnote.com/

    • 다만 어떤 면에서는 Ruby DSL이 MIDI 시퀀스보다 의도를 더 명확히 표현함
      실제로 “이제 C단조 아르페지오, 이제 F장조 아르페지오”처럼 생각할 때가 있고, 그런 의도를 함수로 아주 분명하게 작곡할 수 있는 점이 좋음
    • Sonic Pi는 일반적인 작곡 도구라기보다 알고리즘으로 만든 음악, 특히 라이브 코딩에 더 초점이 있는 것 같음
      음 하나하나를 연주하기보다 알고리즘으로 생성한다는 점이 핵심에 가까워 보임
      그래도 평소라면 쓰지 않을 도구를 특이한 제약 때문에 흥미롭게 활용하는 건 Hacker News의 관심사에 꽤 잘 맞음
    • 협응력과 미세 운동 능력이 부족한 음악 이론가에게는 맞을 수 있음
    • 원글에서도 암시했지만, 대부분은 현실적인 제약 때문임
      마음에 드는 키보드가 있고 이론적으로는 이 작업에 쓸 수도 있지만, 개인적으로 복잡한 사정 때문에 악기들이 한동안 전부 창고에 들어가 있음
  • 며칠 전 마침 Sonic Pi 생각을 하다가 온라인 영상을 몇 개 봤음
    몇 년 전에 잠깐 만져본 게 전부였고, 그때는 고전적인 Old MacDonald와 Hot Cross Buns 같은 곡을 찍어봤음

  • 음악 프로그래밍의 다른 접근법이 궁금하면 라이브는 아니지만 Python용 scamp[0]도 볼 만함
    만든 사람이 YouTube에 이걸로 한 작업 영상을 많이 올렸고, 예를 들면 Fourier Elise 영상[1]이 있음
    [0] http://scamp.marcevanstein.com/
    [1] https://www.youtube.com/watch?v=zq32bIud3OM

  • HTML 주석이 적용되지 않는 것 같음. 에디터가 -- 두 개의 하이픈을 하나의 em dash로 바꿔버린 듯함

    • 잘 짚었음. 사실 찾기/바꾸기를 너무 성급하게 돌리다가 이런 걸 몇 군데 놓쳤음 XD
  • 내가 가장 좋아하는 Sonic Pi 라이브 코더 alsoknownasrox도 추천함
    https://www.youtube.com/watch?v=wXIvXrBQFkE