2 This file is part of GNUnet.
3 (C) 2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file conversation/gnunet-helper-audio-record.c
22 * @brief program to record audio data from the microphone
23 * @author Siomon Dieterle
24 * @author Andreas Fuchs
25 * @author Christian Grothoff
28 #include "gnunet_util_lib.h"
29 #include "gnunet_protocols.h"
30 #include "conversation.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_core_service.h"
34 #include <pulse/simple.h>
35 #include <pulse/error.h>
36 #include <pulse/rtclock.h>
38 #include <pulse/pulseaudio.h>
39 #include <opus/opus.h>
40 #include <opus/opus_types.h>
43 #define DEBUG_RECORD_PURE_OGG 1
48 #define SAMPLING_RATE 48000
51 * How many ms of audio to buffer before encoding them.
53 * 60, 40, 20, 10, 5, 2.5
55 #define FRAME_SIZE_MS 40
58 * How many samples to buffer before encoding them.
60 #define FRAME_SIZE (SAMPLING_RATE / 1000 * FRAME_SIZE_MS)
63 * Pages are commited when their size goes over this value.
64 * Note that in practice we flush pages VERY often (every frame),
65 * which means that pages NEVER really get to be this big.
66 * With one-packet-per-page, pages are roughly 100-300 bytes each.
68 * This value is chosen to make MAX_PAYLOAD_BYTES=1024 fit
71 #define PAGE_WATERLINE 800
74 * Maximum length of opus payload
76 #define MAX_PAYLOAD_BYTES 1024
84 * Configures the encoder's expected packet loss percentage.
86 * Higher values will trigger progressively more loss resistant behavior
87 * in the encoder at the expense of quality at a given bitrate
88 * in the lossless case, but greater quality under loss.
90 #define CONV_OPUS_PACKET_LOSS_PERCENTAGE 1
93 * Configures the encoder's computational complexity.
95 * The supported range is 0-10 inclusive with 10 representing
96 * the highest complexity.
98 #define CONV_OPUS_ENCODING_COMPLEXITY 10
101 * Configures the encoder's use of inband forward error correction (FEC).
103 * Note: This is only applicable to the LPC layer.
105 #define CONV_OPUS_INBAND_FEC 1
108 * Configures the type of signal being encoded.
110 * This is a hint which helps the encoder's mode selection.
113 * OPUS_AUTO - (default) Encoder detects the type automatically.
114 * OPUS_SIGNAL_VOICE - Bias thresholds towards choosing LPC or Hybrid modes.
115 * OPUS_SIGNAL_MUSIC - Bias thresholds towards choosing MDCT modes.
117 #define CONV_OPUS_SIGNAL OPUS_AUTO
123 * OPUS_APPLICATION_VOIP - gives best quality at a given bitrate for voice
124 * signals. It enhances the input signal by high-pass filtering and
125 * emphasizing formants and harmonics. Optionally it includes in-band forward
126 * error correction to protect against packet loss. Use this mode for typical
127 * VoIP applications. Because of the enhancement, even at high bitrates
128 * the output may sound different from the input.
129 * OPUS_APPLICATION_AUDIO - gives best quality at a given bitrate for most
130 * non-voice signals like music. Use this mode for music and mixed
131 * (music/voice) content, broadcast, and applications requiring less than
132 * 15 ms of coding delay.
133 * OPUS_APPLICATION_RESTRICTED_LOWDELAY - configures low-delay mode that
134 * disables the speech-optimized mode in exchange for slightly reduced delay.
135 * This mode can only be set on an newly initialized or freshly reset encoder
136 * because it changes the codec delay.
138 #define CONV_OPUS_APP_TYPE OPUS_APPLICATION_VOIP
141 * Specification for recording. May change in the future to spec negotiation.
143 static pa_sample_spec sample_spec = {
144 .format = PA_SAMPLE_FLOAT32LE,
145 .rate = SAMPLING_RATE,
149 GNUNET_NETWORK_STRUCT_BEGIN
151 /* OggOpus spec says the numbers must be in little-endian order */
152 struct OpusHeadPacket
157 uint16_t preskip GNUNET_PACKED;
158 uint32_t sampling_rate GNUNET_PACKED;
159 uint16_t gain GNUNET_PACKED;
160 uint8_t channel_mapping;
163 struct OpusCommentsPacket
166 uint32_t vendor_length;
168 char vendor[vendor_length];
169 uint32_t string_count;
170 followed by @a string_count pairs of:
171 uint32_t string_length;
172 char string[string_length];
176 GNUNET_NETWORK_STRUCT_END
179 * Pulseaudio mainloop api
181 static pa_mainloop_api *mainloop_api;
184 * Pulseaudio mainloop
186 static pa_mainloop *m;
191 static pa_context *context;
194 * Pulseaudio recording stream
196 static pa_stream *stream_in;
199 * Pulseaudio io events
201 static pa_io_event *stdio_event;
206 static OpusEncoder *enc;
209 * Buffer for encoded data
211 static unsigned char *opus_data;
214 * PCM data buffer for one OPUS frame
216 static float *pcm_buffer;
219 * Length of the pcm data needed for one OPUS frame
221 static int pcm_length;
226 static char *transmit_buffer;
229 * Length of audio buffer
231 static size_t transmit_buffer_length;
234 * Read index for transmit buffer
236 static size_t transmit_buffer_index;
239 * Audio message skeleton
241 static struct AudioMessage *audio_message;
246 static ogg_stream_state os;
251 static int32_t packet_id;
254 * Ogg granule for current packet
256 static int64_t enc_granulepos;
258 #ifdef DEBUG_RECORD_PURE_OGG
260 * 1 to not to write GNUnet message headers,
261 * producing pure playable ogg output
263 static int dump_pure_ogg;
267 * Pulseaudio shutdown task
272 mainloop_api->quit (mainloop_api, ret);
278 write_data (const char *ptr, size_t msg_size)
283 while (off < msg_size)
285 ret = write (1, &ptr[off], msg_size - off);
289 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "write");
297 write_page (ogg_page *og)
299 static unsigned long long toff;
301 msg_size = sizeof (struct AudioMessage) + og->header_len + og->body_len;
302 audio_message->header.size = htons ((uint16_t) msg_size);
303 memcpy (&audio_message[1], og->header, og->header_len);
304 memcpy (((char *) &audio_message[1]) + og->header_len, og->body, og->body_len);
307 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
308 "Sending %u bytes of audio data (total: %llu)\n",
309 (unsigned int) msg_size,
311 #ifdef DEBUG_RECORD_PURE_OGG
313 write_data ((const char *) &audio_message[1], og->header_len + og->body_len);
316 write_data ((const char *) audio_message, msg_size);
320 * Creates OPUS packets from PCM data
331 while (transmit_buffer_length >= transmit_buffer_index + pcm_length)
334 &transmit_buffer[transmit_buffer_index],
336 transmit_buffer_index += pcm_length;
338 opus_encode_float (enc, pcm_buffer, FRAME_SIZE, opus_data,
343 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
344 _("opus_encode_float() failed: %s. Aborting\n"),
345 opus_strerror (len));
348 if (len > UINT16_MAX - sizeof (struct AudioMessage))
354 /* As per OggOpus spec, granule is calculated as if the audio
355 had 48kHz sampling rate. */
356 enc_granulepos += FRAME_SIZE * 48000 / SAMPLING_RATE;
358 op.packet = (unsigned char *) opus_data;
362 op.granulepos = enc_granulepos;
363 op.packetno = packet_id++;
364 ogg_stream_packetin (&os, &op);
366 while (ogg_stream_flush_fill (&os, &og, PAGE_WATERLINE))
368 if (og.header_len + og.body_len > UINT16_MAX - sizeof (struct AudioMessage))
377 new_size = transmit_buffer_length - transmit_buffer_index;
380 nbuf = pa_xmalloc (new_size);
382 &transmit_buffer[transmit_buffer_index],
384 pa_xfree (transmit_buffer);
385 transmit_buffer = nbuf;
389 pa_xfree (transmit_buffer);
390 transmit_buffer = NULL;
392 transmit_buffer_index = 0;
393 transmit_buffer_length = new_size;
398 * Pulseaudio callback when new data is available.
401 stream_read_callback (pa_stream * s,
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
408 "Got %u/%u bytes of PCM data\n",
412 GNUNET_assert (NULL != s);
413 GNUNET_assert (length > 0);
415 mainloop_api->io_enable (stdio_event, PA_IO_EVENT_OUTPUT);
417 if (pa_stream_peek (s, (const void **) &data, &length) < 0)
419 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
420 _("pa_stream_peek() failed: %s\n"),
421 pa_strerror (pa_context_errno (context)));
425 GNUNET_assert (NULL != data);
426 GNUNET_assert (length > 0);
427 if (NULL != transmit_buffer)
429 transmit_buffer = pa_xrealloc (transmit_buffer,
430 transmit_buffer_length + length);
431 memcpy (&transmit_buffer[transmit_buffer_length],
434 transmit_buffer_length += length;
438 transmit_buffer = pa_xmalloc (length);
439 memcpy (transmit_buffer, data, length);
440 transmit_buffer_length = length;
441 transmit_buffer_index = 0;
449 * Exit callback for SIGTERM and SIGINT
452 exit_signal_callback (pa_mainloop_api * m,
457 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
458 _("Got signal, exiting.\n"));
464 * Pulseaudio stream state callback
467 stream_state_callback (pa_stream * s, void *userdata)
469 GNUNET_assert (NULL != s);
471 switch (pa_stream_get_state (s))
473 case PA_STREAM_CREATING:
474 case PA_STREAM_TERMINATED:
476 case PA_STREAM_READY:
478 const pa_buffer_attr *a;
479 char cmt[PA_CHANNEL_MAP_SNPRINT_MAX];
480 char sst[PA_SAMPLE_SPEC_SNPRINT_MAX];
482 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
483 _("Stream successfully created.\n"));
485 if (!(a = pa_stream_get_buffer_attr (s)))
487 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
488 _("pa_stream_get_buffer_attr() failed: %s\n"),
489 pa_strerror (pa_context_errno
490 (pa_stream_get_context (s))));
495 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
496 _("Buffer metrics: maxlength=%u, fragsize=%u\n"),
497 a->maxlength, a->fragsize);
499 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
500 _("Using sample spec '%s', channel map '%s'.\n"),
501 pa_sample_spec_snprint (sst, sizeof (sst),
502 pa_stream_get_sample_spec (s)),
503 pa_channel_map_snprint (cmt, sizeof (cmt),
504 pa_stream_get_channel_map (s)));
506 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
507 _("Connected to device %s (%u, %ssuspended).\n"),
508 pa_stream_get_device_name (s),
509 pa_stream_get_device_index (s),
510 pa_stream_is_suspended (s) ? "" : "not ");
513 case PA_STREAM_FAILED:
515 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
516 _("Stream error: %s\n"),
517 pa_strerror (pa_context_errno (pa_stream_get_context (s))));
524 * Pulseaudio context state callback
527 context_state_callback (pa_context * c,
532 switch (pa_context_get_state (c))
534 case PA_CONTEXT_CONNECTING:
535 case PA_CONTEXT_AUTHORIZING:
536 case PA_CONTEXT_SETTING_NAME:
538 case PA_CONTEXT_READY:
543 GNUNET_assert (!stream_in);
544 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
545 _("Connection established.\n"));
547 pa_stream_new (c, "GNUNET_VoIP recorder", &sample_spec, NULL)))
549 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
550 _("pa_stream_new() failed: %s\n"),
551 pa_strerror (pa_context_errno (c)));
554 pa_stream_set_state_callback (stream_in, &stream_state_callback, NULL);
555 pa_stream_set_read_callback (stream_in, &stream_read_callback, NULL);
556 memset (&na, 0, sizeof (na));
557 na.maxlength = UINT32_MAX;
558 na.fragsize = pcm_length;
559 if ((r = pa_stream_connect_record (stream_in, NULL, &na,
560 PA_STREAM_ADJUST_LATENCY)) < 0)
562 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
563 _("pa_stream_connect_record() failed: %s\n"),
564 pa_strerror (pa_context_errno (c)));
570 case PA_CONTEXT_TERMINATED:
573 case PA_CONTEXT_FAILED:
575 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
576 _("Connection failure: %s\n"),
577 pa_strerror (pa_context_errno (c)));
596 if (!pa_sample_spec_valid (&sample_spec))
598 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
601 /* set up main record loop */
602 if (!(m = pa_mainloop_new ()))
604 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
605 _("pa_mainloop_new() failed.\n"));
607 mainloop_api = pa_mainloop_get_api (m);
609 /* listen to signals */
610 r = pa_signal_init (mainloop_api);
611 GNUNET_assert (r == 0);
612 pa_signal_new (SIGINT, &exit_signal_callback, NULL);
613 pa_signal_new (SIGTERM, &exit_signal_callback, NULL);
615 /* connect to the main pulseaudio context */
617 if (!(context = pa_context_new (mainloop_api, "GNUNET VoIP")))
619 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
620 _("pa_context_new() failed.\n"));
622 pa_context_set_state_callback (context, &context_state_callback, NULL);
623 if (pa_context_connect (context, NULL, 0, NULL) < 0)
625 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
626 _("pa_context_connect() failed: %s\n"),
627 pa_strerror (pa_context_errno (context)));
629 if (pa_mainloop_run (m, &i) < 0)
631 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
632 _("pa_mainloop_run() failed.\n"));
645 pcm_length = FRAME_SIZE * CHANNELS * sizeof (float);
646 pcm_buffer = pa_xmalloc (pcm_length);
647 opus_data = GNUNET_malloc (MAX_PAYLOAD_BYTES);
648 enc = opus_encoder_create (SAMPLING_RATE,
652 opus_encoder_ctl (enc,
653 OPUS_SET_PACKET_LOSS_PERC (CONV_OPUS_PACKET_LOSS_PERCENTAGE));
654 opus_encoder_ctl (enc,
655 OPUS_SET_COMPLEXITY (CONV_OPUS_ENCODING_COMPLEXITY));
656 opus_encoder_ctl (enc,
657 OPUS_SET_INBAND_FEC (CONV_OPUS_INBAND_FEC));
658 opus_encoder_ctl (enc,
659 OPUS_SET_SIGNAL (OPUS_SIGNAL_VOICE));
666 struct OpusHeadPacket headpacket;
667 struct OpusCommentsPacket *commentspacket;
668 size_t commentspacket_len;
670 serialno = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 0x7FFFFFFF);
672 /*Initialize Ogg stream struct*/
673 if (-1 == ogg_stream_init (&os, serialno))
675 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
676 _("ogg_stream_init() failed.\n"));
689 memcpy (headpacket.magic, "OpusHead", 8);
690 headpacket.version = 1;
691 headpacket.channels = CHANNELS;
692 headpacket.preskip = GNUNET_htole16 (0);
693 headpacket.sampling_rate = GNUNET_htole32 (SAMPLING_RATE);
694 headpacket.gain = GNUNET_htole16 (0);
695 headpacket.channel_mapping = 0; /* Mono or stereo */
697 op.packet = (unsigned char *) &headpacket;
698 op.bytes = sizeof (headpacket);
702 op.packetno = packet_id++;
703 ogg_stream_packetin (&os, &op);
705 /* Head packet must be alone on its page */
706 while (ogg_stream_flush (&os, &og))
711 commentspacket_len = sizeof (*commentspacket);
712 opusver = opus_get_version_string ();
713 vendor_length = strlen (opusver);
714 commentspacket_len += vendor_length;
715 commentspacket_len += sizeof (uint32_t);
717 commentspacket = (struct OpusCommentsPacket *) malloc (commentspacket_len);
718 if (NULL == commentspacket)
720 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
721 _("Failed to allocate %d bytes for second packet\n"),
726 memcpy (commentspacket->magic, "OpusTags", 8);
727 commentspacket->vendor_length = GNUNET_htole32 (vendor_length);
728 memcpy (&commentspacket[1], opusver, vendor_length);
729 *(uint32_t *) &((char *) &commentspacket[1])[vendor_length] = \
730 GNUNET_htole32 (0); /* no tags */
732 op.packet = (unsigned char *) commentspacket;
733 op.bytes = commentspacket_len;
737 op.packetno = packet_id++;
738 ogg_stream_packetin (&os, &op);
740 /* Comment packets must not be mixed with audio packets on their pages */
741 while (ogg_stream_flush (&os, &og))
746 free (commentspacket);
751 * The main function for the record helper.
753 * @param argc number of arguments from the command line
754 * @param argv command line arguments
755 * @return 0 ok, 1 on error
758 main (int argc, char *argv[])
760 GNUNET_assert (GNUNET_OK ==
761 GNUNET_log_setup ("gnunet-helper-audio-record",
764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
765 "Audio source starts\n");
766 audio_message = GNUNET_malloc (UINT16_MAX);
767 audio_message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
769 #ifdef DEBUG_RECORD_PURE_OGG
770 dump_pure_ogg = getenv ("GNUNET_RECORD_PURE_OGG") ? 1 : 0;