Вот программа воспроизведения звука с использованием 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);
}