지수 ADSR 엔벨로프 방정식에 대한 도움말


11

애플리케이션 코드를 사용하여 발진기 출력의 진폭을 형성하기 위해 선형 ADSR 엔벨로프를 구현했습니다. 엔벨로프에 서스테인 레벨뿐만 아니라 공격, 붕괴 및 릴리즈 기간에 대한 파라미터를 설정할 수 있으며 모든 것이 예상대로 작동합니다.

그러나 봉투의 경사면 모양을 대부분의 신시사이저가 더 자연스러운 반응을 위해 사용하는 것과 유사한 것으로 조정하고 싶습니다. 이러한 유형의 램프 모양에 대한 엔벨로프 출력 값을 계산하기 위해 수식을 올바르게 작성하는 데 문제가 있습니다. 선형 램프를 계산하기 위해 공격 / 붕괴 / 지속 / 릴리스 입력 매개 변수 값에서 파생 된 시작 / 끝 / y 값을 연결하는 2 점 형식을 사용하고 있습니다. 동일한 시작 / 끝 x / y 포인트 값을 사용하여 지수 (표준 및 역) 램프에 대한 올바른 공식을 계산할 수 없습니다 .xy엑스와이

위에서 설명한 선형 램프에 대한 접근 방식을 보여주는 Desmos Graphing Calculator 세션 을 저장 했습니다 .

누구든지 올바른 방향으로 나를 가리킬 수 있다면 대단히 감사하겠습니다.

답변:


10

나는 당신을 혼란스럽게하는 것은 지수의 감소 ( )가 0에 도달하지 않기 때문에 진정 지수 세그먼트를 가진 ADSR 생성기는 여전히 멈춰있을 것이라고 생각합니다. 목표 값에 도달하지 않기 때문입니다. 예를 들어, 생성기가 공격 단계의 높이에있는 경우 (예 : y =이자형엑스 )에 있고 y = 0.5 의 서스테인 값으로 랜딩해야하는 경우 실제 지수가 원하기 때문에 실제 지수로 갈 수 없습니다. t 0.5로 감소하면 무의식적으로 0.5로만 이동합니다!와이=1와이=0.5

아날로그 엔벨로프 제너레이터 (예 : 7555 기반 회로가 모두 사용하는 것으로 보임 )를 보면, 어택 단계에서 커패시터가 충전 될 때 끝을 나타내는 데 사용 된 임계 값보다 "목표로 높음"을 알 수 있습니다. 공격 단계의. + 15V로 구동되는 (7) 555 기반 회로에서, 공격 단계 동안 커패시터는 + 15V 단계로 충전되지만 + 10V의 임계 값에 도달하면 공격 단계가 종료됩니다. 2/3는 많은 클래식 엔벌 로프 제너레이터에서 볼 수있는 "매직 넘버" 이지만 이것은 음악가에게 친숙한 사람 일 수 있습니다.

커패시터 충전 중 서로 다른 "목표 비율"로 인해 발생하는 일부 ADSR 모양

따라서 처리하려는 함수는 지수가 아니라 이동 / 절단 / 크기 조정 버전이므로 원하는 "분할"방법을 선택해야합니다.

어쨌든 당신이 왜 그런 공식을 얻으려고하는지 궁금합니다. 어쩌면 합성에 사용하는 도구의 한계 때문일 것입니다. 그러나 봉투의 각 샘플에 대해 실행되는 코드와 "상태"라는 개념으로 범용 프로그래밍 언어 (C, java, python)를 사용하여 구현하려는 경우 항상 읽으십시오 ... "그러한 세그먼트는 방금 도달 한 값에서 0으로 이동합니다"와 같이 표현하십시오.

봉투 구현에 대한 두 가지 조언.

첫 번째는 아닙니다엔벨로프가 시작 및 종료 값에 정확하게 도달하도록 모든 기울기 / 증분을 조정하려고합니다. 예를 들어, 2 초 안에 0.8에서 0.2가되는 엔벨로프를 원하므로 -0.3 / 초 단위로 계산하려고 할 수 있습니다. 그렇게하지 마십시오. 대신, 2 단계로 나눕니다 : 2 초 안에 0에서 1.0으로가는 램프를 얻는 것; 0에서 0.8로, 1.0에서 0.2로 매핑되는 선형 변환을 적용합니다. 이 방법으로 작동하는 데는 두 가지 장점이 있습니다. 첫 번째는 엔벨로프 시간에 대한 계산을 0에서 1까지의 램프로 단순화한다는 것입니다. 두 번째는 엔벨로프 매개 변수 (증가 및 시작 / 종료 시간)를 중간에 변경하면 모든 것이 올바르게 작동한다는 것입니다. 사람들이 포락선 시간 매개 변수를 변조 대상으로 요구하기 때문에 신디사이저에서 작업하는 경우 좋습니다.

두 번째는 봉투 모양의 미리 계산 된 조회 테이블을 사용하는 것입니다. 계산적으로 더 가벼우 며 많은 더티 디테일을 제거합니다 (예를 들어 지수가 정확히 0에 도달하지 않음으로 귀찮게 할 필요가 없습니다-변덕에서 자르고 크기를 조정하여 [0, 1]에 매핑됩니다), 각 단계마다 봉투 모양을 변경할 수있는 옵션을 제공하기가 쉽지 않습니다.

여기 내가 설명하는 접근법에 대한 의사 코드가 있습니다.

render:
  counter += increment[stage]
  if counter > 1.0:
    stage = stage + 1
    start_value = value
    counter = 0
  position = interpolated_lookup(envelope_shape[stage], counter)
  value = start_value + (target_level[stage] - start_value) * position

trigger(state):
  if state = ON:
    stage = ATTACK
    value = 0  # for mono-style envelopes that are reset to 0 on new notes
    counter = 0
  else:
    counter = 0
    stage = RELEASE

initialization:
  target_level[ATTACK] = 1.0
  target_level[RELEASE] = 0.0
  target_level[END_OF_RELEASE] = 0.0
  increment[SUSTAIN] = 0.0
  increment[END_OF_RELEASE] = 0.0

configuration:
  increment[ATTACK] = ...
  increment[DECAY] = ...
  target_level[DECAY] = target_level[SUSTAIN] = ...
  increment[RELEASE] = ...
  envelope_shape[ATTACK] = lookup_table_exponential
  envelope_shape[DECAY] = lookup_table_exponential
  envelope_shape[RELEASE] = lookup_table_exponential

y = ((y2-y1) / (x2-x1)) * (x-x1) + y1의 선형 스케일 / 2 포인트 방정식을 취하여 x 문제를 e로 대체하여 문제를 해결하는 것처럼 보였습니다. ^ x ~ y = ((y2-y1) / (e ^ x2-e ^ x1)) * (e ^ x-e ^ x1) + y1. 링크 에서 내 계산기 세션 이이 접근법을 보여줍니다. 내가 알아야 할 점이 있습니까? 결과가 나에게 맞는 것 같습니다.
Gary DeReese 2016 년

다른 신디사이저에서 볼 수있는 봉투 모양이 아닙니다. 시작 및 종료 레벨의 시간 / 상대 위치에 따라 매우 선형이 될 수 있습니다.
pichenettes 2016 년

@pichenettes, 봉투를 생성 한 스크립트를 붙여 넣을 수 있습니까?
I P

3

이것은 꽤 오래된 질문이지만 피케 네트의 대답에서 요점을 강조하고 싶습니다.

예를 들어 2 초 안에 0.8에서 0.2로가는 봉투를 원합니다. [...] 2 단계로 나눕니다 : 2 초 안에 0에서 1.0으로가는 경사로를 얻는 것; 0에서 0.8로, 1.0에서 0.2로 매핑되는 선형 변환을 적용합니다.

이 과정은 때때로 "완화"로 알려져 있으며 다음과 같습니다.

(엑스,,)=에프(엑스)()+

01에프(엑스)엑스01

에프(엑스)

* OP는 오래 전에 사라진 것 같지만 다른 사람에게 도움이 될 수 있습니다.


감사합니다. 개발자 인 DAW 용 샘플러를 프로그래밍하고 Desmos 세션에서 제공 한 공식을 연결했으며 완벽하게 작동했습니다. 더 이상 절름발이 선형 봉투! :)
Douglas Douglas

1

"공격 단계 동안 커패시터는 + 15V 단계로 충전되지만 + 10V의 임계 값에 도달하면 공격 단계가 종료됩니다. 2/3는"마법 "이지만 ""는 많은 클래식 엔벨로프 생성기에서 찾을 수 있으며 이는 음악가에게 친숙 할 수도 있습니다. ":

실제로 10v 대상으로 15v 점근선을 촬영하는 모든 봉투는 선형 공격을 생성합니다. 15v는 쉽게 사용할 수있는 가장 높은 점근선이며 선형에 가깝습니다. 즉, 그것에 대한 "마법"은 없습니다. 그것들은 가능한 한 선형 적으로 진행되고 있습니다.

15v를 사용하는 몇 개의 클래식 신디사이저인지 모르겠습니다. 종종 다이오드 드롭이 하나 또는 두 개있을 것으로 생각됩니다. 내 오래된 Aries 모듈은 10v 엔벨로프에 13v를 사용하고 방금 5v 엔벨로프에 6.5v를 사용하는 Curtis ADSR 칩을 찾았습니다.


1

이 코드는 피케 네트와 유사한 플롯을 생성해야합니다.

def ASD_envelope( nSamps, tAttack, tRelease, susPlateau, kA, kS, kD ):
    # number of samples for each stage
    sA = int( nSamps * tAttack )
    sD = int( nSamps * (1.-tRelease) )
    sS = nSamps - sA - sD

    # 0 to 1 over N samples, weighted with w
    def weighted_exp( N, w ):
        t = np.linspace( 0, 1, N )
        E = np.exp( w * t ) - 1
        E /= max(E)
        return E

    A = weighted_exp( sA, kA )
    S = weighted_exp( sS, kS )
    D = weighted_exp( sD, kD )

    A = A[::-1]
    A = 1.-A

    S = S[::-1]
    S *= 1-susPlateau
    S += susPlateau

    D = D[::-1]
    D *= susPlateau

    env = np.concatenate( [A,S,D] )

    # plot
    tEnv = np.linspace( 0, nSamps, len(env) )
    plt.plot( tEnv, env )
    plt.savefig( "OUT/EnvASD.png" )
    plt.close()

    return env

개선 사항에 대해 감사드립니다. 좋은 아이디어는 마지막 세 가지 매개 변수 (세 단계 각각의 가파른 정도를 결정)가 0과 1 사이에서 달라 지도록 허용하는 것입니다. 여기서 0.5는 직선입니다. 그러나 나는 그것을하는 법을 알 수 없다.

또한 한 스테이지의 길이가 0 인 경우와 같이 모든 사용 사례를 철저히 테스트하지 않았습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.