[go: up one dir, main page]

File: dither.c

package info (click to toggle)
audiotools 3.1.1-1
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 18,200 kB
  • sloc: ansic: 417,746; python: 59,089; xml: 1,639; makefile: 303; sh: 99
file content (108 lines) | stat: -rw-r--r-- 3,565 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/********************************************************
 Audio Tools, a module and set of tools for manipulating audio data
 Copyright (C) 2007-2015  Brian Langenberger

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*******************************************************/

/*This is a set of reusable routines for opening a BitstreamReader
  wrapped around the os.urandom function call
  for generating individual bits of dither for an audio stream.*/

/*this is quite similar to br_read_python
  except that it pulls data from os.urandom()*/
static unsigned
read_os_random(void *user_data,
               uint8_t* buffer,
               unsigned buffer_size)
{
    PyObject *os_module = user_data;
    /*call unrandom() function on os module*/
    PyObject* read_result =
        PyObject_CallMethod(os_module, "urandom", "I", buffer_size);
    char *string;
    Py_ssize_t string_size;
    unsigned to_copy;

    if (read_result == NULL) {
        /*some exception occurred, so clear result and return no bytes
          (which will likely turn into an I/O exception later)*/
        PyErr_Clear();
        return 0;
    }

    /*get string data from returned object*/
    if (PyBytes_AsStringAndSize(read_result,
                                &string,
                                &string_size) == -1) {
        /*got something that wasn't a string from .read()
          so clear exception and return no bytes*/
        Py_DECREF(read_result);
        PyErr_Clear();
        return 0;
    }

    /*write either "buffer_size" or "string_size" bytes to buffer
      whichever is less*/
    if (string_size >= buffer_size) {
        /*truncate strings larger than expected*/
        to_copy = buffer_size;
    } else {
        to_copy = (unsigned)string_size;
    }

    memcpy(buffer, (uint8_t*)string, to_copy);

    /*perform cleanup and return bytes actually read*/
    Py_DECREF(read_result);

    return to_copy;
}

static int
close_os_random(void *user_data)
{
    return 0;
}

static void
free_os_random(void *user_data)
{
    PyObject *os_module = user_data;
    Py_XDECREF(os_module);
}

/*returns a BitstreamReader for reading 1 bit white noise dither values
  or NULL if an error occurs opening the os module*/
static BitstreamReader*
open_dither(void)
{
    PyObject* os_module;

    if ((os_module = PyImport_ImportModule("os")) != NULL) {
        return br_open_external(os_module,
                                BS_BIG_ENDIAN,
                                4096,
                                read_os_random,
                                NULL, /*unseekable stream*/
                                NULL, /*unseekable stream*/
                                NULL, /*unseekable stream*/
                                NULL, /*unseekable stream*/
                                close_os_random,
                                free_os_random);
    } else {
        return NULL;
    }
}