블록 캔버스에는 음원 파일이 없습니다. 배경음을 mp3로 넣지 않고 코드가 그 자리에서 만들어 냅니다. 용량이 0이고, 템포나 음색을 바꾸고 싶으면 숫자만 고치면 됩니다. 아래는 9월 15일에 손본 상태를 기준으로 적었습니다.

대신 파일을 재생할 때는 생각할 필요도 없던 것들이 문제가 됩니다. 그중 제일 먼저 부딪힌 것이 반복 지점이었습니다.

반복음은 끝에서 갑자기 끊기면 안 됩니다

배경음은 128 BPM짜리 8마디를 PCM16 데이터로 만들어 계속 돌립니다. 여기까지는 쉽습니다.

문제는 마지막 박에서 친 소리입니다. 소리는 치는 순간 끝나지 않고 꼬리를 끌면서 잦아듭니다. 그런데 버퍼는 8마디에서 딱 끝납니다. 그 꼬리가 버퍼 바깥으로 넘어갑니다.

그냥 잘라 버리면 반복할 때마다 소리가 뚝 끊기고 다시 시작합니다. 한 번은 몰라도 몇 바퀴 돌면 그 끊김이 박자처럼 들립니다.

그래서 소리를 버퍼에 더할 때 위치를 버퍼 길이로 감습니다. 끝을 넘어가는 부분이 버퍼 맨 앞에 더해집니다. 다음 바퀴가 시작될 때 지난 바퀴의 꼬리가 거기 남아 있는 셈입니다. 테이프를 고리로 이어 붙인 것과 같습니다.

이렇게 짰다는 것이 "모든 환경에서 이음매가 안 들린다"는 뜻은 아닙니다. 기기와 이어폰에 따라 다르게 들릴 수 있고, 거기까지는 확인하지 못했습니다.

만드는 쪽과 내보내는 쪽을 갈라 놓았습니다

음악을 계산하는 일은 build_loop()에 있고, 실제로 소리를 내는 일은 오디오 플레이어에 있습니다. 갈라 놓은 이유는 계산 쪽을 노드 트리나 오디오 장치 없이 돌릴 수 있게 하기 위해서입니다.

만드는 데에는 스레드를 씁니다. 다만 화면과 오디오 장치를 만지는 부분까지 다른 스레드로 밀어 넣지는 않았습니다. 그쪽은 엔진이 메인 스레드를 전제하는 자리라 건드리면 조용히 깨집니다.

갈라 놓고 나니 확인할 것도 둘로 갈립니다.

  • 숫자로 확인되는 것 — 만들어진 데이터의 길이가 맞는지, 샘플 값이 범위를 넘지 않는지. 이건 자동으로 셉니다
  • 귀로만 확인되는 것 — 이음매가 들리는지, 배경음이 효과음을 덮는지. 이건 판을 돌리면서 들어 보는 수밖에 없습니다

둘은 서로 대신하지 못합니다. 숫자가 다 통과해도 듣기 싫을 수 있고, 듣기 좋아도 값이 범위를 넘어 다른 기기에서 깨질 수 있습니다.

소리 전체와 배경음을 따로 끕니다

저장 쪽에 bgm_on이 따로 있고 설정 화면의 배경음 토글이 거기 물려 있습니다. 끈 선택은 저장되고 다음에 켤 때 그대로 돌아옵니다.

소리를 하나로 묶지 않은 이유는 간단합니다. 효과음은 듣고 싶은데 배경음만 끄고 싶은 사람이 있습니다. 저도 다른 게임에서 그렇게 씁니다. 하나로 묶어 두면 그 사람은 소리를 통째로 끄고, 그러면 블록이 맞을 때 나는 소리까지 같이 사라집니다.

확인할 상황기대하는 동작
배경음 끄기배경음 재생 설정에 즉시 반영
앱 종료 후 다시 실행저장한 선택 복원
무음 검증 모드저장 설정과 관계없이 소리를 내지 않음
화면 전환·재시작재생기가 중복 생성되지 않는지 확인

마지막 줄이 특히 잘 빠집니다. 화면을 오가다 재생기가 둘이 되면 같은 음악이 살짝 어긋난 채로 겹쳐 들립니다. 소리가 "이상한데 뭐가 이상한지 모르겠는" 상태가 되는데, 원인을 찾기 전까지는 음악 자체를 의심하게 됩니다.

아직 남겨 둔 확인 범위

이 글은 scripts/bgm.gd, game.gd, save.gd 를 읽고 적은 것입니다. 스피커나 이어폰으로 오래 들어 본 결과도, 휴대폰 전력을 잰 값도, 새 Play 배포를 마쳤다는 보고도 아닙니다. 그쪽은 따로 시험해야 합니다.

다른 게임에 같은 구조를 넣으신다면 순서를 권해 드립니다. 짧은 반복음을 먼저 만들고, 반복 경계 → 음량 → 중복 재생 → 설정 복원 순서로 확인하십시오. 음악을 길게 만드는 것은 그다음입니다. 무엇보다 사용자가 끌 수 있는 경로를 먼저 마련하는 쪽이 낫습니다. 끄지 못하는 배경음은 아무리 잘 만들어도 그냥 소음입니다.

이어서 읽을 것

게임은 블록 캔버스 소개에서 이어집니다. 보드를 넓히면서 생긴 문제들은 더 넓은 보드에 적었습니다. 소리를 코드로 만드는 다른 사례로는 음악이 조여 오게 만들기가 있는데, 그쪽은 반복이 아니라 긴장을 올리는 쪽이라 셈이 다릅니다.