앰프 시뮬레이션 플러그인...

저녁밥이 준비되는 동안 간단한 테스팅 프로그램을 만들어 확인해본 결과, 피드백이 positive로 들어가고 있다는 걸 발견했다. 수정 후에는 feedback loop까지 완벽하게 동작하게 되었다.

연산량을 줄이기 위해 oversampling은 생략했지만, 그 덕에 aliasing이 약간 생기긴 해도 충분히 쓸만한 수준이다.

이 정도 load라면 지금까지 사용해본 다른 플러그인들—허접한 드라이브 페달들 포함해서—과 비교해도 큰 차이가 없는 수준이다. 실제로 복잡도를 그만큼 낮췄기에 가능한 일이다.

덕분에 보기 싫던 코드를 싹 정리하면서, 이른바 refactoring을 통해 코드가 훨씬 깔끔하고 보기 좋게 바뀌었다.

생각해보면, 코드가 지저분해졌던 주된 이유는 옛날 C++ 컴파일러들이 표준을 제대로 지원하지 못했기 때문이다. 그런 환경에선 추상화도 어렵고, 메모리 관리도 일일이 손으로 해줘야 했으니 지저분해질 수밖에 없었다.

하지만 지금은 C++만으로도 충분히 깔끔하고, 보기 좋은 코드를 작성할 수 있다. 추상화도 잘 되고, 메모리 관리도 예전처럼 번거롭지 않다. 게다가 성능도 느리지 않고, 결과물도 작다.

물론 garbage collection이 잘 되는 다른 언어들을 써보면 처음엔 꽤 매력적이다. 하지만 learning curve도 있고, 실제로 작성해보면 실행 속도가 너무 느려서 결국은 다시 C++로 돌아오게 된다. Rust도 그랬고, Swift도 마찬가지였다. 성능을 올리려면 결국 누군가 C++로 만들어놓은 라이브러리를 호출해서 쓰는 수밖에 없다.

예전엔 printf 대신 cout만 써도 코드 크기가 10배는 늘어났던 시절이 있었다. 속도는 측정해보지 않았지만, 체감상 확실히 느려졌다. 같은 기능을 클래스 기반으로 짜기만 해도 코드 크기는 훨씬 커졌고, 속도는 떨어졌으며, 문제 생기면 디버깅도 어려웠다. 그러다보니 C++의 OOP적인 장점은 거의 못 써먹은 셈이다.

지금은 그런 제약이 많이 사라졌다. 덕분에 리팩토링을 하면 코드가 짧아지고 깔끔해지며, 어디 내놔도 자랑스러울 만한 수준이 된다.

여기서 테스트의 중요성을 다시금 실감하게 된다. 대부분은 처음부터 코드가 완벽하게 돌아갈 거라 착각하지만, 실제로 테스트해보면 가장 단순한 블록에서조차 문제가 가장 많이 발견된다.

리팩토링한 결과물은 현재 1959SLP와 JTM45 모델에 적용해보았다. 유튜브에 올라온 실제 앰프 테스트 영상과 비교해도 대부분 비슷한 톤을 내고 있다.

다만, 기타 앰프 사운드는 오래 듣다보면 특정 주파수 대역에만 귀가 예민해지는 경향이 있어서, 그럴싸하다고 느꼈던 사운드가 며칠 후 다시 들어보면 엉망처럼 들릴 때도 있다. 그래서 보통은 2~3일 쉬고 다시 들어보는 게 중요하다. 그때 들리는 소리가 진짜다.