Forum: Mikrocontroller und Digitale Elektronik ADSR Funktion


von Klaus (Gast)


Lesenswert?

Hallo,

ich erzeuge Töne mit Hilfe einer Sinustabelle und gebe diese mit einem 
Abdac zum Verstärker.

Jetzt möchte ich eine ADSR Hüllkurve integrieren damit das etwas 
vernünftig klingt.

Hat jemand Tips, Code oder Anleitung wie man sowas in C 
implementiert(möglichst einfach)?

von Ben j. (scarab)


Lesenswert?

Du musst nur deinen Sinus mit der ADSR-Kurve multiplizieren bevor du ihn 
zum DAC gibst wobei die Kurve dann ein Gleitkommawert von 0 bis 1 ist.

Wenn du bei integer bleiben willst dann dividiere den Sinus durch (255 - 
ADSR_Wert) bei 8Bit bzw. (65535 - ADSR_Wert) bei 16Bit usw.

Code könnte dann ungefähr so aussehen:
1
uint16 u16_ADSR_Wert;     //aktueller Wert zum "dividieren" mit dem sinus
2
uint16 au16_ADSR_Dauer[4];  //Dauer der Abschnitte
3
uint16 au16_ADSR_Hoehe[2];  //Höhe des A uns S Abschnittes
4
boolean b_taste;    //true wenn taste gedrückt wurde
5
6
typedef enum
7
{
8
  ph_Nix
9
  ph_A
10
  ph_D
11
  ph_S
12
  ph_R
13
}EN_PHASEN
14
15
EN_PHASEN en_phase;
16
17
void Timer_1_ms(void)
18
{
19
  static uint16 u16_time;
20
  if( b_taste == TRUE )
21
  {  
22
    //Tastendruck verarbeiten
23
    en_phase = ph_A;
24
    u16_time = 0;
25
    b_taste = FALSE;
26
  }
27
  
28
  if( en_phase == ph_A )
29
  {
30
    if( u16_time < au16_ADSR_Dauer[0] )
31
    {
32
      u16_ADSR_Wert = ( au16_ADSR_Hoehe[0] / au16_ADSR_Dauer[0] ) * u16_time;
33
      u16_time++;
34
    }
35
    else
36
    {
37
      //nächste Phase
38
      en_phase = ph_D;
39
      u16_time = 0;
40
    }
41
  }
42
  elseif( en_phase == ph_D )
43
  {
44
    if( u16_time < au16_ADSR_Dauer[1] )
45
    {
46
      u16_ADSR_Wert = ( (au16_ADSR_Hoehe[0]-au16_ADSR_Hoehe[1]) / au16_ADSR_Dauer[1] ) * (au16_ADSR_Dauer[1]-u16_time) + au16_ADSR_Hoehe[1];
47
      u16_time++;
48
    }
49
    else
50
    {
51
      //nächste Phase
52
      en_phase = ph_S;
53
      u16_time = 0;
54
    }
55
  }
56
  elseif( en_phase == ph_S )
57
  {
58
    if( u16_time < au16_ADSR_Dauer[2] )
59
    {
60
      u16_ADSR_Wert = au16_ADSR_Hoehe[1];
61
      u16_time++;
62
    }
63
    else
64
    {
65
      //nächste Phase
66
      en_phase = ph_R;
67
      u16_time = 0;
68
    }
69
  }
70
  elseif( en_phase == ph_R )
71
  {
72
    if( u16_time < au16_ADSR_Dauer[3] )
73
    {
74
      u16_ADSR_Wert = ( au16_ADSR_Hoehe[1] / au16_ADSR_Dauer[3] ) * (au16_ADSR_Dauer[3]-u16_time);
75
      u16_time++;
76
    }
77
    else
78
    {
79
      //nächste Phase
80
      en_phase = ph_Nix;
81
      u16_time = 0;
82
    }
83
  }
84
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.