Sitzung: Jeden Freitag in der Vorlesungszeit ab 16 Uhr c. t. im MAR 0.005. In der vorlesungsfreien Zeit unregelmäßig (Jemensch da?). Macht mit!

C-Kurs/DTMF-Encoder/Musterlösung

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

unsigned char* generateSine(int ms, int freq, float amplitude, int *numSamples) {
    /* calculate number of samples and factor for the sine function */
    *numSamples = ms * 8; // 8000 Hz sampling rate means 8 samples per millisecond
    double numPeriodic = 8000.0 / freq;
    double sinFac = 2 * M_PI / numPeriodic;

    unsigned char *sine = malloc(*numSamples * sizeof(unsigned char));

    /* generate samples */
    int i;
    for (i = 0; i < *numSamples; i++) {
        double sineVal = sin(i * sinFac);  // between -1 and 1
        unsigned char sample = (unsigned char) ((amplitude * sineVal + 1) * 0x7f);
        sine[i] = sample;
    }

    return sine;
}

unsigned char* mixPcm(unsigned char *a, unsigned char *b, int numSamples) {
    unsigned char *result = malloc(numSamples * sizeof(unsigned char));
    int i;
    for (i = 0; i < numSamples; i++) {
        int aVal = a[i] - 127;
        int bVal = b[i] - 127;
        int rVal = aVal + bVal;
        result[i] = (unsigned char)(rVal + 127);
    }
    return result;
}

unsigned char* generateDtmfTone(int number, int ms, int *numSamples) {
    unsigned char *a;
    unsigned char *b;
    unsigned char *result;
    switch (number) {
        case 0:
            a = generateSine(ms, 941, 0.45, numSamples);
            b = generateSine(ms, 1336, 0.45, numSamples);
            break;
        case 1:
            a = generateSine(ms, 697, 0.45, numSamples);
            b = generateSine(ms, 1209, 0.45, numSamples);
            break;
        case 2:
            a = generateSine(ms, 697, 0.45, numSamples);
            b = generateSine(ms, 1336, 0.45, numSamples);
            break;
        case 3:
            a = generateSine(ms, 697, 0.45, numSamples);
            b = generateSine(ms, 1477, 0.45, numSamples);
            break;
        case 4:
            a = generateSine(ms, 770, 0.45, numSamples);
            b = generateSine(ms, 1209, 0.45, numSamples);
            break;
        case 5:
            a = generateSine(ms, 770, 0.45, numSamples);
            b = generateSine(ms, 1336, 0.45, numSamples);
            break;
        case 6:
            a = generateSine(ms, 770, 0.45, numSamples);
            b = generateSine(ms, 1477, 0.45, numSamples);
            break;
        case 7:
            a = generateSine(ms, 852, 0.45, numSamples);
            b = generateSine(ms, 1209, 0.45, numSamples);
            break;
        case 8:
            a = generateSine(ms, 852, 0.45, numSamples);
            b = generateSine(ms, 1336, 0.45, numSamples);
            break;
        case 9:
            a = generateSine(ms, 852, 0.45, numSamples);
            b = generateSine(ms, 1477, 0.45, numSamples);
            break;
    }
    result = mixPcm(a, b, *numSamples);
    free(a);
    free(b);
    return result;
}

unsigned char *generateSilence(int ms, int *numSamples) {
    *numSamples = ms * 8; // 8000 Hz sampling rate means 8 samples per millisecond
    unsigned char *result = malloc(*numSamples * sizeof(unsigned char));
    int i;
    for (i = 0; i < *numSamples; i++) {
        result[i] = 127;
    }
    return result;
}

int main(int argc, char **argv) {
    if (argc != 2) {
        fprintf(stderr, "no number given\n");
        return 0;
    }

    int number;
    if (1 != sscanf(argv[1], "%u", &number)) {
        fprintf(stderr, "given argument is not a number\n");
        return 0;
    }

    FILE *f = fopen(argv[1], "w");

    char *curNum = argv[1];
    while (*curNum != '\0') {
        int digit = *curNum++ - '0';

        int numSamples;
        unsigned char *tone = generateDtmfTone(digit, 800, &numSamples);
        fwrite(tone, sizeof(unsigned char), numSamples, f);
        free(tone);
        tone = generateSilence(300, &numSamples);
        fwrite(tone, sizeof(unsigned char), numSamples, f);
        free(tone);
    }

    fclose(f);
}