2012-11-03 1 views
4

저는 학습 프로젝트로서 어셈블리에 간단한 신스를 작성하고 있습니다. 근대 신디사이저에있는 몇 가지 고급 기능, 즉 ADSR 인 벨롭과 펄스 폭 변조를 구현하고 싶습니다. 사인파. 지금은 기본적으로 샘플을 손으로 생성하고 샘플 버퍼와 버퍼가 거의 비어있을 때 생성되는 인터럽트가있는 오디오 출력으로 샘플을 푸시합니다.어셈블리 오디오 합성을위한 데이터 구조

내가 계속 붙어있는 것은 '연속적인'파형을 생성하는 방법입니다. 지금은 파도의 단일 인스턴스에 대한 샘플을 생성하고 (톱 또는 펄스 임), 그 하나의 웨이브를 반복하여 연속 출력을 생성합니다. 상상할 수 있듯이 PWM 및 ADSR 엔벨로프에는 잘 맞지 않습니다. 따라서 펄스 폭이나 피치 (예 : 레가토)의 변조와 같이 즉석에서 조정할 수있는 온 디맨드 방식의 웨이브를 생성해야하지만,이를 메모리에서 효율적으로 표현하는 방법에 관해서는 난처한 편입니다 , 버퍼가 채워 졌을 때 웨이브 폼 생성을 '일시 중지'하고 인터럽트가 발생할 때 '다시 시작'하는 방법도 있습니다.

내가

감사합니다 :-) 생각하는 올바른 방향으로 찔러으로 너무 많은 해결책을 찾는 게 아니에요

!

답변

1

파도를 발생시키는 방법은 감산 합성에 적합한 방법입니다. 파형의 PWM을 조정하려면 샘플을 재생성 (또는 메모리에 저장된 사전 계산 된 파형 검색)해야합니다.

피치가 변경되면 대부분의 경우 웨이브 테이블도 다시 작성해야합니다. 웨이브 기본에 비해 읽기 포인터 증분을 계산하여 더 빠른 속도로 웨이브를 읽을 수 있지만 웨이브 테이블의 값을 보간해야하며 더 복잡한 웨이브를 사용하여 앨리어싱을 도입 할 수 있습니다.

물론 대부분의 경우 생성 된 웨이브가 정확히 2^n 샘플이 될 것 같지 않습니다. 따라서 프로세스 루틴의 시작 부분에서 현재 웨이브를 출력 버퍼에 복사하기 전에 이전 웨이브의 샘플을 먼저 복사하십시오.

재생 프로세스가 DSP 프로세스 루틴을 방해하지 않도록하려면 별도의 메모리 위치에 업데이트 된 파형을 구성하고 준비가되면 복사하십시오.

웨이브 자체에 영향을 미치기보다는 웨이브가 생성 된 후 ADSR 엔벨로프 (감산 방식)를 이동 이득 계수로 적용해야합니다. 도움이 :) 간단한 파도 일 것이다 수요에 파도를 생성

+0

그래서 RAM에 어딘가에 파형을 생성 한 다음, 직접 렌더링 대신 신경 쓰지 않고 피드하는 것이 좋습니다. 그러나 지금은 단 하나의 파도 만 가지고 있습니다. 더 복잡한 물결이 메모리 어딘가에 저장되면 어떻게 임의의 길이의 지속과 같은 일을 할 것인가? 미리 렌더링 된 샘플에서 '루프 포인트'를 설정하는 것에 대해 생각했지만 주파수 나 펄스 폭을 변조하는 경우 루프는 잠재적으로 방대한 길이가되어야합니다.나는 퍼즐 조각을 놓치고 있다고 생각합니다. – dmkc

+0

신디가 어떻게 구동되는지 더 알고 싶습니다. 대부분의 플러그인 이펙트/신스 (익숙한)의 경우 클라이언트는 주기적으로 '프로세스'기능을 호출하여 샘플 2 블록의 출력을 요청합니다. DSP에 대한 업데이트는 프로세스 요청간에 매개 변수로 변경된 이벤트 콜백을 통해 수행됩니다. 구현이 비슷합니까? – elSnape

+0

그와 비슷합니다. 예. 제 질문은 대부분 피치와 펄스 폭 변조를 고려하여 2^2의 블록을 생성하는 방법에 관한 것입니다. – dmkc

1

을 나중에 추가 기능을 추가하려는 경우/당신은 여전히 ​​버퍼의 어떤 종류가 필요합니다 DSP는 있지만

희망. 당신은 단지 파형의 크기를 조절하기 때문에 진폭

ADSR는 기사가 link 또한

당신이 farbraush github에 확인할 수 있습니다,이 있어야 몇 가지에 대해 설명하고 여기에 조금 더 복잡 주파수 변조를 들어, 매우 간단하다 좋은 영감을 얻을 수 있습니다.