Laden...

CAPI-Wrapper

Erstellt von tom-essen vor 17 Jahren Letzter Beitrag vor 14 Jahren 67.472 Views
H
240 Beiträge seit 2006
vor 15 Jahren

Nabend,

ich hab leider meinen ganzen ISDN-Kram nicht hier bei meinen Eltern, deshalb ist das jetzt nur ein Schuss ins Blaue:

Du schreibst ja, du stellst die Verbindung her und "nimmst ab", also rufst du ein (ISDN-)Telefon an? Ich glaube mich erinnern zu können, dass Gespräche aber gar nicht auf B3-Ebene ablaufen, oder irre ich mich da jetzt total?

Würde aber erklären, warum die Gegenstelle dir kein Connect_B3_Active_Ind schickt.
Hast du eventuell eine Möglichkeit, eine Verbindung mit einer ISDN-Karte zur Datenübertragung herzustellen?

Oder sonst erreichst du unter der Nummer 0171 / 2521001 das SMSC von T-Mobile (darüber kann man per TAP-Protokoll SMS in das T-Mobile-Netz schicken, ich erwähne es nur, weil ich damit gearbeitet hab und deshalb weiss, dass es funktioniert). Wenn du da eine B3_Active_Ind bekommst, weisst du zumindest, dass deine Implementierung richtig ist, danach kannst du ja die Verbindung beenden.
Aber vorsicht, das kostet so viel wie ein Anruf auf einem D1 Handy!

Falls ich mit meiner Vermutung daneben liege weiss ich leider auch nicht weiter, hab mich lange nicht mit ISDN beschäftigt...

MfG hulkstar

tom-essen Themenstarter:in
1.820 Beiträge seit 2005
vor 15 Jahren

Hallo!

@hulkstar:
Danke für den Tipp, aber leider hat es (zumindest mit der T-Mobile-Nr.) nicht funktioniert (welcher CIP-Value wäre dafür zu verwenden?). Die andere Alternative (zu anderer ISDN-Karte zwecks Datenübertragung) werde ich beizeiten Mal testen und berichten.

EDIT: Das CONNECT_B3_ACTIVE_IND vermisse ich übrigens deshalb, weil es in der CAPI-Doku (Teil 1, Seite 133) als Abschluss-Event angegeben wird.

EDIT2: Kennt vielleicht jemand noch weitere Quellen /Bücher, ausser capi.org?

Nobody is perfect. I'm sad, i'm not nobody 🙁

H
240 Beiträge seit 2006
vor 15 Jahren

Hallo Tom,

welcher CIP-Value wäre dafür zu verwenden?

der CIP-Value, den ich verwendet habe ist '2', also "unrestricted digital information".
Mit CIP == 1 ("speech") geht es nicht. Daran hab ich auch ne weile gehangen...

Das CONNECT_B3_ACTIVE_IND vermisse ich übrigens deshalb, weil es in der CAPI-Doku (Teil 1, Seite 133) als Abschluss-Event angegeben wird.

Genau da hab ich auch immer hingeguckt aber wie gesagt, mir "war so", als würde Sprache nicht auf B3-Ebene ablaufen. Aber da will ich mich nicht festlegen...! Ich habe mich immer nur um Datenübertragung (SMS) gekümmert.

Kennt vielleicht jemand noch weitere Quellen /Bücher, ausser capi.org?

Leider nicht. In der Hinsicht war es wirklich von Vorteil, dass ich bei T-Mobile saß, die haben noch ein paar interne Dokmente, bzw. mein Betreuer hat das auch schon lange gemacht... 😉

Ich weiss nicht, ob Elli diesen Thread abonniert hat, vielleicht schreibst du ihm einfach mal eine PM. So wie ich das mitbekommen habe, programmiert er seit 20? Jahren ISDN...

Und dann gab es auch hier im Forum mal jemanden, der Sprache über ISDN gemach hat (das war eine frage zu der Umwandlung), der müsse ja dann auch wissen, ob dazu die B3-Ebene nötig ist.

MfG hulkstar

tom-essen Themenstarter:in
1.820 Beiträge seit 2005
vor 15 Jahren

Hallo!

Hab' heute mal versucht, die Original capi2032.dll mit einer eigenen c-dll zu kapseln, um die aufgerufenen Methoden und übergebenen Datenstrukturen zu loggen, aber leider bin ich nicht allzu gut in c und nach dem letzten vs-Absturz hab' ich dieses Vorhaben dann erstmal aufgegeben. Hat evtl. einer so etwas schonmal gemacht, oder kennt eine entsprechende Bezugsquelle (ausser shamrock, avm.de und capi.org).

Nobody is perfect. I'm sad, i'm not nobody 🙁

tom-essen Themenstarter:in
1.820 Beiträge seit 2005
vor 15 Jahren

Hallo!

@all:
Ich konnte nun endlich eine B3-Verbindung aufbauen. Der Fehler lag in einer von mir falsch erstellen B3_REQ-Struktur.

Jetzt muss ich mich darum kümmern, eine Verbindung auch wieder korrekt zu trennen.

Nobody is perfect. I'm sad, i'm not nobody 🙁

tom-essen Themenstarter:in
1.820 Beiträge seit 2005
vor 15 Jahren

Hallo!

Bin gerade dabei, den CAPI-Wrapper soweit zu entschlacken, dass wirklich nur noch die für den direkten CAPI-Zugriff benötigten Funktionen, Strukturen und Konstanten drin sind. Alles weiterführende habe ich in eine auf dem Wrapper aufbauende DLL ausgelagert.
Parallel dazu versuche ich gerade, in der Connection-Klasse die Funktionalität für Voice und Fax zu integrieren, so dass man sowohl Sprache senden und empfangen kann, als auch Faxe senden und empfangen kann. Bei Voice soll zusätzlich die Möglichkeit gegeben werden, die ALAW-Daten in WAV zu konvertieren und umgekehrt.

Da ich dafür z.Zt. aber nur am Wochenende Zeit finde, wird es wohl noch ein paar Wochen dauern, bis das Ganze halbwegs vernünftig läuft.

Nobody is perfect. I'm sad, i'm not nobody 🙁

194 Beiträge seit 2006
vor 15 Jahren

@Tom Essen

vielleicht findest du diesen Artikel auch interessan( wenn du ihn natürlich nicht schon kennst)
http://www.codeproject.com/KB/cs/Streaming_wave_audio.aspx

Es geht um Voice via CAPI ich hatte bis anhin nur das Glück, das ganze via directshow.net und via generiertem Filtergraphen zu bewerkstelligen.
Wurde eine riesenApp.

Einfach mit Codec-Tabellen schaffte ich nur wave-dateien in annehmbarer qualität.
Weiss nicht hab nur eine Fritz-USB zur Hand.

MFG

Balaban S

tom-essen Themenstarter:in
1.820 Beiträge seit 2005
vor 15 Jahren

Hallo!

@Balaban_S:
Danke für den Hinweis, den Artikel kannte ich noch nicht, werd' ich mir demnächst mal anschauen.
Ton aufnehmen und abspielen funktioniert aber mittlerweile bei mir auch, d.h. einen einfachen Anrufbeantworter konnte ich mir schon schreiben, nur das Timing muss ich noch verbessern, hab' ab und zu noch ein paar Ruckler.

Nobody is perfect. I'm sad, i'm not nobody 🙁

56 Beiträge seit 2006
vor 14 Jahren

Hallo zusammen,

ich befasse mich nun auch aus beruflichen Gründen mit der Thematik.
Leider kommt bei der "testcapi.zip" eine Fehlermeldung:

Lock System

Your expiration date is reached! You need to purchase a license to run this software.

Hmm... habe ich doch erst heute installiert 😉.

Gibt es aktuellere Erkenntnisse zu dem Thema CAPI ?
Gibt es Bibliotheken, die man direkt in C# verwenden kann ?

Ich bin in Begriff ein Programm zu schreiben, welches einen ankommenden Ruf entgegen nimmt und dann auf die Eingabe eines Tastendrucks wartet (MFV-Töne).

Da die Posts schon etwas älter sind:Ist jemand von Euch aktuell noch dabei etwas in der Richtung zu programmieren ?

Evtl. kann man sich zusammen tun 😉.

Viele Grüße

Ylirebus

Die Bugs verhalten sich proportional zu den Codezeilen und nehmen exponential zu.(Ich bin nicht doof, ich denke nur anders. 😉)
Ich fühle mich als wäre ich diagonal in einem Paralleluniversum abgestellt worden.

tom-essen Themenstarter:in
1.820 Beiträge seit 2005
vor 14 Jahren

Hallo!

@YLIREBUS:
Bzgl. der testcapi.zip: Die muss ich wohl mal aktualisieren.

Bzgl. der Aktualität:
Am Wrapper wird nach wie vor gearbeitet, z.Zt. versuche ich, das gesamte Konstruct etwas dynamischer zu gestalten, so dass der Wrapper später bei Bedarf durch andere Komponenten ausgetauscht werden kann (z.B. für CAPI over Ethernet, oder ähnliches).

Bzgl. der MFV-Töne:
Da hast du dir was vorgenommen. Ich bin z.Zt. dabei, Fax-Support zu integrieren, und da geht es ebenfalls um Töne (die beim Fax üblichen Piep- und Pfeiftöne) mit Träger- und Datenfrequenz, die per Algorithmus getrennt werden müssen.

Aber da können wir uns gerne mal kurzschließen. Kannst mich ja per PM oder ICQ ansprechen.

Nobody is perfect. I'm sad, i'm not nobody 🙁

56 Beiträge seit 2006
vor 14 Jahren

OK, prima werde ich machen,

ich bin allerdings gerade dabei die Grundlagen zu erforschen und wie ich am Besten vorgehe.

Eigentlich haben wir ein Asterisk Telefonanlage, die mit dem SIP-Protokoll arbeitet, aber da etwas über MFV zu finden ist mir nicht gelungen.
Nun versuche ich an der Telefonanlage vorbei über ISDN zu gehen und dann mit der CAPI-Schnittstelle zu arbeiten.

Werde mir wohl auch nochmal VS-2005 installieren, da ich das Projekt nicht übersetzen kann in VS-2008

Ich werde meine Erkenntnisse gerne mit Euch teilen 😉.

bis dann

Ylirebus

Die Bugs verhalten sich proportional zu den Codezeilen und nehmen exponential zu.(Ich bin nicht doof, ich denke nur anders. 😉)
Ich fühle mich als wäre ich diagonal in einem Paralleluniversum abgestellt worden.

56 Beiträge seit 2006
vor 14 Jahren

Hallo zusammen,

ich habe da mal was gefunden open source:

http://capi.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=17089

Genau das was ich brauche:

DTFM Erkennung 😉 , C#

Hier kann man zu mindest sehen wie der Hase läuft 😉.

Da dies sicherlich nur der Anfang ist werden wir sicher noch einiges voneinander hören 😉.

Gruß

Ylirebus

Die Bugs verhalten sich proportional zu den Codezeilen und nehmen exponential zu.(Ich bin nicht doof, ich denke nur anders. 😉)
Ich fühle mich als wäre ich diagonal in einem Paralleluniversum abgestellt worden.

tom-essen Themenstarter:in
1.820 Beiträge seit 2005
vor 14 Jahren

Hallo!

@YLIREBUS:
Da hab' ich wohl total in die falsche Richtung gedacht. Da ich mich mit DTMF bisher nicht beschäftigt hatte, war ich wirklich der Meinung, die Töne würden nur akustisch übertragen. So kann man sich täuschen.

Nobody is perfect. I'm sad, i'm not nobody 🙁

E
26 Beiträge seit 2004
vor 14 Jahren

Hallo Tom,

Mann Du bastelst ja immer noch an der CAPI rum ...

DTMF erkennen wird über den Görtzel Algo gemacht. Vor Jahren hatte ich mir mal
aus den erhältlichen Quellen eine Klasse zusammengebastelt. Ich poste sie mal hier
(siehe unten).

Soweit ich in Erinnerung habe, berücksichtigen die Tabellen schon die inverse ISDN Darstellung der ISDN B-Kanal Daten. Meist haben ja die ISDN Karten den DTMF Kram in Form eines Hardware Codecs. Der Code ist nicht super optimiert, kann man
besser machen.

Das Codeplex Projekt kenne ich. Viel zu kompliziert programmiert für meinen Geschmack ...

Wenn Du fragen hast poste sie.

elli

typedef void (CALLBACK * PDTMFSignalProc)(
                                          PVOID pvContext,
                                          char  ch
                                         );


typedef struct
 {
  int freq;
  int grp;        /* low/high group     */
  int k;          /* k                  */
  int k2;         /* k fuer 2. harmonic */
 } TDTMF;

typedef struct
 {
  int freq1;
  int freq2;
 } TFrequenceDesc;


#define MAX_DTMF_TONES     8  + 1
#define NCOEFF             16 + 2     // number of frequencies to be analyzed

class CDTMFCodec
 {
  public:
   CDTMFCodec();

   void init              (
                           DWORD dwNumberSamples,
                           DWORD dwSampleRate = 8000
                          );


   void    setSignalProc(
                         PDTMFSignalProc signalProc,
                         PVOID           signalContext
                        );


   void    scanAlaw          (PBYTE pvBuffer, int iLength );
   void    scan              (PWORD pvBuffer, int iLength );
   BOOL    generateTone      (PWORD buffer, DWORD dwNumOfSamples, char ch);
   void    setCNGDetection   (BOOL bFlag);

  protected:
   virtual void   signalChar (char ch);
           void   scanTones  (int * pvBuffer);
           void   goertzel   (int * pvBuffer);

  private:
    static int            cos2pik[NCOEFF];
    static TDTMF          tones[MAX_DTMF_TONES];
    static char           chMatrix[4][4];
    static TFrequenceDesc freqTones[NCOEFF];

    PDTMFSignalProc       dtmfSignalProc;
    PVOID                 dtmfSignalContext;
    char                  lastChar;
    int                   iIndex;
    int                   pcmBuffer [2048];         // we use int for faster 32 bit access
    int                   tempBuffer[NCOEFF];
    BOOL                  bCNGDetection;
 };


typedef CDTMFCodec * PDTMFCodec;

inline void
CDTMFCodec::signalChar (char ch)
 {
  if ( dtmfSignalProc )
   {
    dtmfSignalProc( dtmfSignalContext, ch );
   }
 }


inline void
CDTMFCodec::setSignalProc(
                          PDTMFSignalProc signalProc,
                          PVOID           signalContext
                         )
 {
  dtmfSignalProc    = signalProc;
  dtmfSignalContext = signalContext;
 }


inline void
CDTMFCodec::setCNGDetection(BOOL bFlag)
 {
  bCNGDetection = bFlag;
 }


//#define DTMF_TRESH   100000   // above this is dtmf
//#define H2_TRESH      20000   // 2nd harmonic

#define DTMF_TRESH     50000     // above this is dtmf
#define H2_TRESH       10000     // 2nd harmonic
#define SILENCE_TRESH    100     // below this is silence

#define AMP_BITS           9     // bits per sample, reduced to avoid overflow
#define DTMF_NPOINTS     205     // Number of samples for DTMF recognition

#define LOGRP              0
#define HIGRP              1
#define MAX_N            384

#define PI            3.1415

#pragma warning (disable : 4309) // Verkuerzung eines konstanten Wertes
#pragma warning (disable : 4305) // Verkuerzung von 'const int' in 'short'

//---------------------------------------------------------------------------
// alaw -> signed 16-bit
//---------------------------------------------------------------------------
static short isdnAlawTo16BitPCM[] =
 {
  0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
  0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
  0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
  0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
  0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
  0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
  0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
  0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
  0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
  0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
  0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
  0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
  0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
  0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
  0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
  0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
  0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
  0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
  0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
  0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
  0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
  0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
  0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
  0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
  0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
  0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
  0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
  0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
  0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
  0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
  0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
  0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
 };


//---------------------------------------------------------------------------
// For dtmf recognition: * 2 * cos(2 * PI * k / N) precalculated for ISDN
// (8000 Hz) and all k
//---------------------------------------------------------------------------
int CDTMFCodec::cos2pik[NCOEFF] =
 {
  55812,  29528, 53603,  24032, 51193,  14443, 48590,   6517,
  38113, -21204, 33057, -32186, 25889, -45081, 18332, -55279, 42450, -10225
 };


//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
TDTMF CDTMFCodec::tones[MAX_DTMF_TONES] =
 {
  { 697, LOGRP, 0,  1 },
  { 770, LOGRP, 2,  3 },
  { 852, LOGRP, 4,  5 },
  { 941, LOGRP, 6,  7 },
  {1209, HIGRP, 8,  9 },
  {1336, HIGRP, 10, 11 },
  {1477, HIGRP, 12, 13 },
  {1633, HIGRP, 14, 15 },
  {1100, HIGRP, 16, 17 }   // FAX CNG detection
 };

//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
char CDTMFCodec::chMatrix[4][4] =
 {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
 };


//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
TFrequenceDesc CDTMFCodec::freqTones[NCOEFF] =
 {
  {697, 1209}, {697, 1336}, {697, 1477}, {697, 1633},
  {770, 1209}, {770, 1336}, {770, 1477}, {770, 1633},
  {852, 1209}, {852, 1336}, {852, 1477}, {852, 1633},
  {941, 1209}, {941, 1336}, {941, 1477}, {941, 1633}, {1100,1100}
 };


//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
CDTMFCodec::CDTMFCodec()
 {
  iIndex            = 0;
  lastChar          = ' ';
  dtmfSignalProc    = NULL;
  dtmfSignalContext = NULL;
  bCNGDetection     = FALSE;
 }


//---------------------------------------------------------------------------
// Der Goertzel-Algorithmus:
// Ist ein genauso schlichtes, wie geniales numerisches Verfahren (!) und
// beinhaltet im Groben "folgendes":
//
// Sog. "Feedback-Phase":
// Ein Schritt bezieht sich immer auf einen Block von 205 Samples
// (also n=0, ... 204) bei 8kHz.
// DTMF hat 8 Frequenzen: 697, 770, 852, 941, 1209, 1336, 1477, 1633 Hz
// Jede Frequenz hat einen eigenen Koeffizienten coef.
// coef = 2 cos(2 * PI * k / N), mit N=205, k=(2N/samplingrate) * DTMF frequenz .
// 4 Parameter sind dabei im Spiel: Q[n] = coef * Q[n-1] - Q[n-2] + Sample[n] .
// Q[n-1] & Q[n-2] werden am anfang gleich Null gesetzt.
// Sog. "Feedforward-Phase":
// Wurden alle 205 Samples verrechnet tritt die sog "Feedforward-Phase" ein.
// "quadrierte Werte": Y=(Q[n-1]) ^2 - (q[n-2])^2 - Q[n-1] * Q[n-2] * coef .
// Y representiert den "Energie-Gehalt" der gesuchten Frequenz.
// Weiter mit dem nächsten Block.
// Dabei kommen idR sehr grosse Werte heraus, so das es Sinn macht, die
// Samples auf doubles zwischen 0 ... 1 zu skalieren
//---------------------------------------------------------------------------
void
CDTMFCodec::goertzel(int * pvBuffer)
 {
  int tempCos2Pik;
  int sk;
  int sk1;
  int sk2;
  int k;
  int n;
  int * result;
  int maxCoefficients;

  if ( bCNGDetection )
   maxCoefficients = NCOEFF + 2;
  else
   maxCoefficients = NCOEFF;

  tempCos2Pik = 0;
  result      = tempBuffer;

  for (k = 0; k < maxCoefficients ; k++)
   {
    tempCos2Pik = cos2pik[k];
    sk          = 0;
    sk1         = 0;
    sk2         = 0;

    for (n = 0; n < DTMF_NPOINTS; n++)
     {
      sk  = pvBuffer[n] + ((tempCos2Pik * sk1) >> 15) - sk2;
      sk2 = sk1;
      sk1 = sk;
     }

    result[k] = ((sk * sk) >> AMP_BITS) -
                (((( tempCos2Pik * sk) >> 15) * sk2) >> AMP_BITS) +
               ((sk2 * sk2) >> AMP_BITS);
   }

  scanTones( tempBuffer );
 }

//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
void
CDTMFCodec::scanAlaw( PBYTE pvBuffer, int iLength )
 {
  int i;
  int c;

  while ( iLength )
   {
    c = min(iLength, (DTMF_NPOINTS - iIndex));
    if (c <= 0) break;

    for (i = 0; i < c; i++)
     {
      pcmBuffer[ iIndex++ ] = isdnAlawTo16BitPCM[*pvBuffer++] >> (15 - AMP_BITS);
     }

    if (iIndex == DTMF_NPOINTS)
     {
      goertzel(pcmBuffer);
      iIndex = 0;
      }

    iLength -= c;
   }
 }


//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
void
CDTMFCodec::scan( PWORD pvBuffer, int iLength )
 {
  int i;
  int c;

  while ( iLength )
   {
    c = min(iLength, (DTMF_NPOINTS - iIndex));
    if (c <= 0) break;

    for (i = 0; i < c; i++)
     {
      pcmBuffer[ iIndex++ ] = *pvBuffer++; // >> (15 - AMP_BITS);
     }

    if (iIndex == DTMF_NPOINTS)
     {
      goertzel(pcmBuffer);
      iIndex = 0;
     }

    iLength -= c;
   }
 }



//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
BOOL
CDTMFCodec::generateTone(PWORD pvBuffer, DWORD dwNumOfSamples, char ch)
 {
  int col, row, idx;
  double f1, f2;
  double value  = 12000.0;
  int i1;
  int i2;

  idx  = -1;
  i1   = 0;
  i2   = 0;
  for (row = 0; row < 4; row++)
   {
    for (col = 0; col < 4; col++)
     {
      if (ch == chMatrix[row][col])
       {
        idx = row * 4 + col;
       }
     }
   }

  if (idx < 0)
   {
    return FALSE;
   }

  f1 = (((double) freqTones[idx].freq1) * PI );
  f2 = (((double) freqTones[idx].freq2) * PI );

  for (idx = 0; idx < (int) dwNumOfSamples; idx++)
   {
    pvBuffer[idx]  = (WORD)(value * sin((double)i1 * f1/4000));
    pvBuffer[idx] = pvBuffer[idx] + (WORD)(value * sin((double)i2 * f2/4000));

    i1++;
    i2++;
   }

  return TRUE;
 }


//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
void
CDTMFCodec::scanTones(int * pvBuffer )
 {
  int *result;
  int silence;
  int i;
  int grp[2];
  char what;

  result     = pvBuffer;
  grp[LOGRP] = -2;
  grp[HIGRP] = -2;
  silence    = 0;

  for (i = 0; i < 8; i++)
   {
    if ( (result[ tones[i].k ] > DTMF_TRESH) && (result[tones[i].k2] < H2_TRESH))
     {
      grp[tones[i].grp] = (grp[tones[i].grp] == -2) ? i : -1;
     }
    else if ((result[tones[i].k] < SILENCE_TRESH) && (result[tones[i].k2] < SILENCE_TRESH))
     {
      silence++;
     }
   }

  if (silence == 8)
   {
    what = ' ';
    if ( bCNGDetection )
     {
      if ( (result[ tones[9].k ] > DTMF_TRESH) && (result[tones[9].k2] < H2_TRESH))
       {
        // start CNG timer

        signalChar( 'F' );
       }
      else
       {
        // stop CNG Timer,  calculate elapsed time
       }
     }
   }
  else
   {
    if ( (grp[LOGRP] >= 0) && (grp[HIGRP] >= 0) )
     {
      what = chMatrix[grp[LOGRP]] [grp[HIGRP] - 4];

      if ( (lastChar != ' ') && (lastChar != '.'))
       {
        lastChar = what;        //  min. 1 non-DTMF between DTMF
       }
     }
    else
     {
      what = '.';
     }
   }

  if ( (what != lastChar) && (what != ' ') && (what != '.'))
   {
    signalChar( what );
   }

  lastChar = what;
 }
tom-essen Themenstarter:in
1.820 Beiträge seit 2005
vor 14 Jahren

Hallo!

@elli:
Ja, bin immer mal wieder dran, wenn ich ein wenig Zeit habe. Danke für deinen Code, denn werd' ich beizeiten mal übersetzen (bin in C nicht ganz so gut).

Nobody is perfect. I'm sad, i'm not nobody 🙁

tom-essen Themenstarter:in
1.820 Beiträge seit 2005
vor 14 Jahren

Hallo!

Nachdem ich darauf hingewiesen wurde, dass die letzt Version nicht mehr funktioniert, hab' ich im ersten Beitrag einen neuen Link (Am Ende im Abschnitt "Download") hinzugefügt. Getestet hab' ich's auf 2000, XP und Vista.

Da ich aktuell nicht all zu viel Zeit in die CAPI-Entwicklung stecken kann, möge man mir bitte nachsehen, wenn ich auf Fragen erst etwas verzögert reagiere.

Nobody is perfect. I'm sad, i'm not nobody 🙁