Звук звука JACK, измененный при воспроизведении - PullRequest
0 голосов
/ 12 января 2019

Вот программа воспроизведения звука с использованием JACK, которая работает, но не работает должным образом. Сбой происходит из-за изменения аудиоданных при чтении звуковых данных из файла с помощью файла sndfile, но я не могу понять, почему ... Звук выходит, но уродлив.

Если вы знакомы со звуковым файлом и аудио-комплектом JACK, это, вероятно, будет 5-минутным куском для вас, иначе это может быть сложно.

Если у кого-то есть подсказка или предложение: пожалуйста, не стесняйтесь!

Вот мой код, который открывает wavfile с помощью sndfile и воспроизводит его с JACK:

#include <stdio.h>
#include <stdlib.h>
#include <sndfile.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <jack/jack.h>
#include <jack/ringbuffer.h>

jack_port_t *input_port;
jack_port_t *output_port;
jack_client_t *client;
jack_ringbuffer_t *rb;
#define DEFAULT_RB_SIZE 16384  /*ringbuffer size in frames */
const size_t sample_size = sizeof(jack_default_audio_sample_t);

int
process (jack_nframes_t nframes, void *arg)
{
    jack_default_audio_sample_t *out;
    out = jack_port_get_buffer (output_port, nframes);

    for (int cpt =0; cpt < nframes; cpt++)
    {
        jack_ringbuffer_read (rb, (void *) &out[cpt], 4);
    }

    return 0;
}

void
jack_shutdown (void *arg)
{
    exit (1);
}

int main()
{
    SNDFILE *sf;
    SF_INFO info;
    int num_channels;
    int num, num_items;
    int *buf;
    int f,sr,c;
    int i,j;

    /* Open the WAV file. */
    info.format = 0;
    sf = sf_open("fileAudio.wav",SFM_READ,&info);
    if (sf == NULL)
    {
        printf("Failed to open the file.\n");
        exit(-1);
    }
    /* Print some of the info, and figure out how much data to read. */
    f = info.frames;
    sr = info.samplerate;
    c = info.channels;
    printf("frames=%d\n",f);
    printf("samplerate=%d\n",sr);
    printf("channels=%d\n",c);
    num_items = f*c;
    printf("num_items=%d\n",num_items);
    /* Allocate space for the data to be read, then read it. */
    buf = (int *) malloc(num_items*sizeof(int));
    num = sf_read_int(sf,buf,2250);//num_items);

/* Begin Jack setup */
const char **ports;
const char *client_name = "simple";
const char *server_name = NULL;
jack_options_t options = JackNullOption;
jack_status_t status;

rb = jack_ringbuffer_create(DEFAULT_RB_SIZE * sample_size);

/* Open a client connection to the JACK server */
client = jack_client_open (client_name, options, &status, server_name);
if (client == NULL) {
    fprintf (stderr, "jack_client_open() failed, "
        "status = 0x%2.0x\n", status);
    if (status & JackServerFailed) {
        fprintf (stderr, "Unable to connect to JACK server\n");
    }
    exit (1);
}
if (status & JackServerStarted) {
    fprintf (stderr, "JACK server started\n");
}
if (status & JackNameNotUnique) {
    client_name = jack_get_client_name(client);
    fprintf (stderr, "unique name `%s' assigned\n", client_name);
}

/* tell the JACK server to call `process()' whenever
   there is work to be done.*/
jack_set_process_callback (client, process, 0);

/* tell the JACK server to call 'jack_shutdown()' if
   it ever shuts down, either entirely, or if it
   just decides to stop calling us.*/
jack_on_shutdown (client, jack_shutdown, 0);

/* display the current sample rate. */
printf ("engine sample rate: %" PRIu32 "\n",
    jack_get_sample_rate (client));

/* create port */
output_port = jack_port_register (client, "output",
                JACK_DEFAULT_AUDIO_TYPE,
                JackPortIsOutput, 0);

if (output_port == NULL) {
    fprintf(stderr, "no more JACK ports available\n");
    exit (1);
}

/* Tell the JACK server that we are ready to roll. Our
 * process() callback will start running now. */

if (jack_activate (client)) {
    fprintf (stderr, "cannot activate client");
    exit (1);
}

/* Connect the ports. You can't do this before the client is 
 * activated, because we can't make connectons to clients 
 * that aren't running. Note the confusing (but necessary)
 * orientation of the driver backend ports: playback ports are
 * "input" to the backend, and capture ports are "output" from it
 */
ports = jack_get_ports (client, NULL, NULL,
            JackPortIsPhysical|JackPortIsInput);
if (ports == NULL) {
    fprintf(stderr, "no physical playback ports\n");
    exit (1);
}

if (jack_connect (client, jack_port_name (output_port), ports[0])) {
    fprintf (stderr, "cannot connect output ports\n");
}

free (ports);

/* keep running until stopped by the user */

while (1)
{
    if (jack_ringbuffer_write_space (rb) >= 4000)
    {
        jack_ringbuffer_write (rb, (char*) buf, 4000);
        sf_read_int(sf, buf, 1000);
    }
}

/* this is never reached but if the program 
   had some other way to exit besides deing killed,
   they woud be important to call.*/

jack_client_close (client);
exit (0);
}
...