glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / conversation / gnunet-helper-audio-record.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2013 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
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      Affero General Public License for more details.
14 */
15 /**
16  * @file conversation/gnunet-helper-audio-record.c
17  * @brief program to record audio data from the microphone
18  * @author Siomon Dieterle
19  * @author Andreas Fuchs
20  * @author Christian Grothoff
21  */
22 #include "platform.h"
23 #include "gnunet_util_lib.h"
24 #include "gnunet_protocols.h"
25 #include "conversation.h"
26 #include "gnunet_constants.h"
27 #include "gnunet_core_service.h"
28
29 #include <pulse/simple.h>
30 #include <pulse/error.h>
31 #include <pulse/rtclock.h>
32
33 #include <pulse/pulseaudio.h>
34 #include <opus/opus.h>
35 #include <opus/opus_types.h>
36 #include <ogg/ogg.h>
37
38 #define DEBUG_RECORD_PURE_OGG 1
39
40 /**
41  * Sampling rate
42  */
43 #define SAMPLING_RATE 48000
44
45 /**
46  * How many ms of audio to buffer before encoding them.
47  * Possible values:
48  * 60, 40, 20, 10, 5, 2.5
49  */
50 #define FRAME_SIZE_MS 40
51
52 /**
53  * How many samples to buffer before encoding them.
54  */
55 #define FRAME_SIZE (SAMPLING_RATE / 1000 * FRAME_SIZE_MS)
56
57 /**
58  * Pages are commited when their size goes over this value.
59  * Note that in practice we flush pages VERY often (every frame),
60  * which means that pages NEVER really get to be this big.
61  * With one-packet-per-page, pages are roughly 100-300 bytes each.
62  *
63  * This value is chosen to make MAX_PAYLOAD_BYTES=1024 fit
64  * into a single page.
65  */
66 #define PAGE_WATERLINE 800
67
68 /**
69  * Maximum length of opus payload
70  */
71 #define MAX_PAYLOAD_BYTES 1024
72
73 /**
74  * Number of channels
75  */
76 #define CHANNELS 1
77
78 /**
79  * Configures the encoder's expected packet loss percentage.
80  *
81  * Higher values will trigger progressively more loss resistant behavior
82  * in the encoder at the expense of quality at a given bitrate
83  * in the lossless case, but greater quality under loss.
84  */
85 #define CONV_OPUS_PACKET_LOSS_PERCENTAGE 1
86
87 /**
88  * Configures the encoder's computational complexity.
89  *
90  * The supported range is 0-10 inclusive with 10 representing
91  * the highest complexity.
92  */
93 #define CONV_OPUS_ENCODING_COMPLEXITY 10
94
95 /**
96  * Configures the encoder's use of inband forward error correction (FEC).
97  *
98  * Note: This is only applicable to the LPC layer.
99  */
100 #define CONV_OPUS_INBAND_FEC 1
101
102 /**
103  * Configures the type of signal being encoded.
104  *
105  * This is a hint which helps the encoder's mode selection.
106  *
107  * Possible values:
108  * OPUS_AUTO - (default) Encoder detects the type automatically.
109  * OPUS_SIGNAL_VOICE - Bias thresholds towards choosing LPC or Hybrid modes.
110  * OPUS_SIGNAL_MUSIC - Bias thresholds towards choosing MDCT modes.
111  */
112 #define CONV_OPUS_SIGNAL OPUS_SIGNAL_VOICE
113
114 /**
115  * Coding mode.
116  *
117  * Possible values:
118  * OPUS_APPLICATION_VOIP - gives best quality at a given bitrate for voice
119  * signals. It enhances the input signal by high-pass filtering and
120  * emphasizing formants and harmonics. Optionally it includes in-band forward
121  * error correction to protect against packet loss. Use this mode for typical
122  * VoIP applications. Because of the enhancement, even at high bitrates
123  * the output may sound different from the input.
124  * OPUS_APPLICATION_AUDIO - gives best quality at a given bitrate for most
125  * non-voice signals like music. Use this mode for music and mixed
126  * (music/voice) content, broadcast, and applications requiring less than
127  * 15 ms of coding delay.
128  * OPUS_APPLICATION_RESTRICTED_LOWDELAY - configures low-delay mode that
129  * disables the speech-optimized mode in exchange for slightly reduced delay.
130  * This mode can only be set on an newly initialized or freshly reset encoder
131  * because it changes the codec delay.
132  */
133 #define CONV_OPUS_APP_TYPE OPUS_APPLICATION_VOIP
134
135 /**
136  * Specification for recording. May change in the future to spec negotiation.
137  */
138 static pa_sample_spec sample_spec = {
139   .format = PA_SAMPLE_FLOAT32LE,
140   .rate = SAMPLING_RATE,
141   .channels = CHANNELS
142 };
143
144 GNUNET_NETWORK_STRUCT_BEGIN
145
146 /* OggOpus spec says the numbers must be in little-endian order */
147 struct OpusHeadPacket
148 {
149   uint8_t magic[8];
150   uint8_t version;
151   uint8_t channels;
152   uint16_t preskip GNUNET_PACKED;
153   uint32_t sampling_rate GNUNET_PACKED;
154   uint16_t gain GNUNET_PACKED;
155   uint8_t channel_mapping;
156 };
157
158 struct OpusCommentsPacket
159 {
160   uint8_t magic[8];
161   uint32_t vendor_length;
162   /* followed by:
163      char vendor[vendor_length];
164      uint32_t string_count;
165      followed by @a string_count pairs of:
166        uint32_t string_length;
167        char string[string_length];
168    */
169 };
170
171 GNUNET_NETWORK_STRUCT_END
172
173 /**
174  * Pulseaudio mainloop api
175  */
176 static pa_mainloop_api *mainloop_api;
177
178 /**
179  * Pulseaudio mainloop
180  */
181 static pa_mainloop *m;
182
183 /**
184  * Pulseaudio context
185  */
186 static pa_context *context;
187
188 /**
189  * Pulseaudio recording stream
190  */
191 static pa_stream *stream_in;
192
193 /**
194  * Pulseaudio io events
195  */
196 static pa_io_event *stdio_event;
197
198 /**
199  * OPUS encoder
200  */
201 static OpusEncoder *enc;
202
203 /**
204  * Buffer for encoded data
205  */
206 static unsigned char *opus_data;
207
208 /**
209  * PCM data buffer for one OPUS frame
210  */
211 static float *pcm_buffer;
212
213 /**
214  * Length of the pcm data needed for one OPUS frame
215  */
216 static int pcm_length;
217
218 /**
219  * Audio buffer
220  */
221 static char *transmit_buffer;
222
223 /**
224  * Length of audio buffer
225  */
226 static size_t transmit_buffer_length;
227
228 /**
229  * Read index for transmit buffer
230  */
231 static size_t transmit_buffer_index;
232
233 /**
234  * Audio message skeleton
235  */
236 static struct AudioMessage *audio_message;
237
238 /**
239  * Ogg muxer state
240  */
241 static ogg_stream_state os;
242
243 /**
244  * Ogg packet id
245  */
246 static int32_t packet_id;
247
248 /**
249  * Ogg granule for current packet
250  */
251 static int64_t enc_granulepos;
252
253 #ifdef DEBUG_RECORD_PURE_OGG
254 /**
255  * 1 to not to write GNUnet message headers,
256  * producing pure playable ogg output
257  */
258 static int dump_pure_ogg;
259 #endif
260
261 /**
262  * Pulseaudio shutdown task
263  */
264 static void
265 quit (int ret)
266 {
267   mainloop_api->quit (mainloop_api,
268                       ret);
269   exit (ret);
270 }
271
272
273 static void
274 write_data (const char *ptr,
275             size_t msg_size)
276 {
277   ssize_t ret;
278   size_t off;
279   off = 0;
280   while (off < msg_size)
281   {
282     ret = write (STDOUT_FILENO,
283                  &ptr[off],
284                  msg_size - off);
285     if (0 >= ret)
286     {
287       if (-1 == ret)
288         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
289                              "write");
290       quit (2);
291     }
292     off += ret;
293   }
294 }
295
296
297 static void
298 write_page (ogg_page *og)
299 {
300   static unsigned long long toff;
301   size_t msg_size;
302   msg_size = sizeof (struct AudioMessage) + og->header_len + og->body_len;
303   audio_message->header.size = htons ((uint16_t) msg_size);
304   GNUNET_memcpy (&audio_message[1], og->header, og->header_len);
305   GNUNET_memcpy (((char *) &audio_message[1]) + og->header_len, og->body, og->body_len);
306
307   toff += msg_size;
308   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
309               "Sending %u bytes of audio data (total: %llu)\n",
310               (unsigned int) msg_size,
311               toff);
312 #ifdef DEBUG_RECORD_PURE_OGG
313   if (dump_pure_ogg)
314     write_data ((const char *) &audio_message[1],
315                 og->header_len + og->body_len);
316   else
317 #endif
318     write_data ((const char *) audio_message,
319                 msg_size);
320 }
321
322
323 /**
324  * Creates OPUS packets from PCM data
325  */
326 static void
327 packetizer ()
328 {
329   char *nbuf;
330   size_t new_size;
331   int32_t len;
332   ogg_packet op;
333   ogg_page og;
334
335   while (transmit_buffer_length >= transmit_buffer_index + pcm_length)
336   {
337     GNUNET_memcpy (pcm_buffer,
338             &transmit_buffer[transmit_buffer_index],
339             pcm_length);
340     transmit_buffer_index += pcm_length;
341     len =
342       opus_encode_float (enc, pcm_buffer, FRAME_SIZE, opus_data,
343                          MAX_PAYLOAD_BYTES);
344
345     if (len < 0)
346     {
347       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
348                   _("opus_encode_float() failed: %s. Aborting\n"),
349                   opus_strerror (len));
350       quit (5);
351     }
352     if (((uint32_t)len) > UINT16_MAX - sizeof (struct AudioMessage))
353     {
354       GNUNET_break (0);
355       continue;
356     }
357
358     /* As per OggOpus spec, granule is calculated as if the audio
359        had 48kHz sampling rate. */
360     enc_granulepos += FRAME_SIZE * 48000 / SAMPLING_RATE;
361
362     op.packet = (unsigned char *) opus_data;
363     op.bytes = len;
364     op.b_o_s = 0;
365     op.e_o_s = 0;
366     op.granulepos = enc_granulepos;
367     op.packetno = packet_id++;
368     ogg_stream_packetin (&os, &op);
369
370     while (ogg_stream_flush_fill (&os, &og, PAGE_WATERLINE))
371     {
372       if ( ((unsigned long long) og.header_len) +
373            ((unsigned long long) og.body_len) >
374            UINT16_MAX - sizeof (struct AudioMessage))
375       {
376         GNUNET_assert (0);
377         continue;
378       }
379       write_page (&og);
380     }
381   }
382
383   new_size = transmit_buffer_length - transmit_buffer_index;
384   if (0 != new_size)
385   {
386     nbuf = pa_xmalloc (new_size);
387     memmove (nbuf,
388              &transmit_buffer[transmit_buffer_index],
389              new_size);
390     pa_xfree (transmit_buffer);
391     transmit_buffer = nbuf;
392   }
393   else
394   {
395     pa_xfree (transmit_buffer);
396     transmit_buffer = NULL;
397   }
398   transmit_buffer_index = 0;
399   transmit_buffer_length = new_size;
400 }
401
402
403 /**
404  * Pulseaudio callback when new data is available.
405  */
406 static void
407 stream_read_callback (pa_stream * s,
408                       size_t length,
409                       void *userdata)
410 {
411   const void *data;
412
413   (void) userdata;
414   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
415               "Got %u/%d bytes of PCM data\n",
416               (unsigned int) length,
417               pcm_length);
418
419   GNUNET_assert (NULL != s);
420   GNUNET_assert (length > 0);
421   if (stdio_event)
422     mainloop_api->io_enable (stdio_event, PA_IO_EVENT_OUTPUT);
423
424   if (pa_stream_peek (s, (const void **) &data, &length) < 0)
425   {
426     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
427                 _("pa_stream_peek() failed: %s\n"),
428                 pa_strerror (pa_context_errno (context)));
429     quit (1);
430     return;
431   }
432   GNUNET_assert (NULL != data);
433   GNUNET_assert (length > 0);
434   if (NULL != transmit_buffer)
435   {
436     transmit_buffer = pa_xrealloc (transmit_buffer,
437                                    transmit_buffer_length + length);
438     GNUNET_memcpy (&transmit_buffer[transmit_buffer_length],
439             data,
440             length);
441     transmit_buffer_length += length;
442   }
443   else
444   {
445     transmit_buffer = pa_xmalloc (length);
446     GNUNET_memcpy (transmit_buffer, data, length);
447     transmit_buffer_length = length;
448     transmit_buffer_index = 0;
449   }
450   pa_stream_drop (s);
451   packetizer ();
452 }
453
454
455 /**
456  * Exit callback for SIGTERM and SIGINT
457  */
458 static void
459 exit_signal_callback (pa_mainloop_api * m,
460                       pa_signal_event * e,
461                       int sig,
462                       void *userdata)
463 {
464   (void) m;
465   (void) e;
466   (void) sig;
467   (void) userdata;
468   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
469               _("Got signal, exiting.\n"));
470   quit (1);
471 }
472
473
474 /**
475  * Pulseaudio stream state callback
476  */
477 static void
478 stream_state_callback (pa_stream * s,
479                        void *userdata)
480 {
481   (void) userdata;
482   GNUNET_assert (NULL != s);
483   switch (pa_stream_get_state (s))
484   {
485   case PA_STREAM_CREATING:
486   case PA_STREAM_TERMINATED:
487     break;
488   case PA_STREAM_READY:
489     {
490       const pa_buffer_attr *a;
491       char cmt[PA_CHANNEL_MAP_SNPRINT_MAX];
492       char sst[PA_SAMPLE_SPEC_SNPRINT_MAX];
493
494       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
495                   _("Stream successfully created.\n"));
496
497       if (!(a = pa_stream_get_buffer_attr (s)))
498       {
499         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
500                     _("pa_stream_get_buffer_attr() failed: %s\n"),
501                     pa_strerror (pa_context_errno
502                                  (pa_stream_get_context (s))));
503
504       }
505       else
506       {
507         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
508                     _("Buffer metrics: maxlength=%u, fragsize=%u\n"),
509                     a->maxlength, a->fragsize);
510       }
511       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
512                   _("Using sample spec '%s', channel map '%s'.\n"),
513                   pa_sample_spec_snprint (sst, sizeof (sst),
514                                           pa_stream_get_sample_spec (s)),
515                   pa_channel_map_snprint (cmt, sizeof (cmt),
516                                           pa_stream_get_channel_map (s)));
517
518       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
519                   _("Connected to device %s (%u, %ssuspended).\n"),
520                   pa_stream_get_device_name (s),
521                   pa_stream_get_device_index (s),
522                   pa_stream_is_suspended (s) ? "" : "not ");
523     }
524     break;
525   case PA_STREAM_FAILED:
526   default:
527     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
528                 _("Stream error: %s\n"),
529                 pa_strerror (pa_context_errno (pa_stream_get_context (s))));
530     quit (1);
531   }
532 }
533
534
535 /**
536  * Pulseaudio context state callback
537  */
538 static void
539 context_state_callback (pa_context * c,
540                         void *userdata)
541 {
542   (void) userdata;
543   GNUNET_assert (c);
544
545   switch (pa_context_get_state (c))
546   {
547   case PA_CONTEXT_CONNECTING:
548   case PA_CONTEXT_AUTHORIZING:
549   case PA_CONTEXT_SETTING_NAME:
550     break;
551   case PA_CONTEXT_READY:
552   {
553     int r;
554     pa_buffer_attr na;
555
556     GNUNET_assert (!stream_in);
557     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
558                 _("Connection established.\n"));
559     if (! (stream_in =
560            pa_stream_new (c, "GNUNET_VoIP recorder", &sample_spec, NULL)))
561     {
562       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
563                   _("pa_stream_new() failed: %s\n"),
564                   pa_strerror (pa_context_errno (c)));
565       goto fail;
566     }
567     pa_stream_set_state_callback (stream_in, &stream_state_callback, NULL);
568     pa_stream_set_read_callback (stream_in, &stream_read_callback, NULL);
569     memset (&na, 0, sizeof (na));
570     na.maxlength = UINT32_MAX;
571     na.fragsize = pcm_length;
572     if ((r = pa_stream_connect_record (stream_in, NULL, &na,
573                                        PA_STREAM_ADJUST_LATENCY)) < 0)
574     {
575       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
576                   _("pa_stream_connect_record() failed: %s\n"),
577                   pa_strerror (pa_context_errno (c)));
578       goto fail;
579     }
580
581     break;
582   }
583   case PA_CONTEXT_TERMINATED:
584     quit (0);
585     break;
586   case PA_CONTEXT_FAILED:
587   default:
588     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
589                 _("Connection failure: %s\n"),
590                 pa_strerror (pa_context_errno (c)));
591     goto fail;
592   }
593   return;
594
595 fail:
596   quit (1);
597 }
598
599
600 /**
601  * Pulsaudio init
602  */
603 static void
604 pa_init ()
605 {
606   int r;
607   int i;
608
609   if (!pa_sample_spec_valid (&sample_spec))
610   {
611     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
612                 _("Wrong Spec\n"));
613   }
614   /* set up main record loop */
615   if (!(m = pa_mainloop_new ()))
616   {
617     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
618                 _("pa_mainloop_new() failed.\n"));
619   }
620   mainloop_api = pa_mainloop_get_api (m);
621
622   /* listen to signals */
623   r = pa_signal_init (mainloop_api);
624   GNUNET_assert (r == 0);
625   pa_signal_new (SIGINT, &exit_signal_callback, NULL);
626   pa_signal_new (SIGTERM, &exit_signal_callback, NULL);
627
628   /* connect to the main pulseaudio context */
629
630   if (!(context = pa_context_new (mainloop_api, "GNUNET VoIP")))
631   {
632     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
633                 _("pa_context_new() failed.\n"));
634   }
635   pa_context_set_state_callback (context, &context_state_callback, NULL);
636   if (pa_context_connect (context, NULL, 0, NULL) < 0)
637   {
638     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
639                 _("pa_context_connect() failed: %s\n"),
640                 pa_strerror (pa_context_errno (context)));
641   }
642   if (pa_mainloop_run (m, &i) < 0)
643   {
644     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
645                 _("pa_mainloop_run() failed.\n"));
646   }
647 }
648
649
650 /**
651  * OPUS init
652  */
653 static void
654 opus_init ()
655 {
656   int err;
657
658   pcm_length = FRAME_SIZE * CHANNELS * sizeof (float);
659   pcm_buffer = pa_xmalloc (pcm_length);
660   opus_data = GNUNET_malloc (MAX_PAYLOAD_BYTES);
661   enc = opus_encoder_create (SAMPLING_RATE,
662                              CHANNELS,
663                              CONV_OPUS_APP_TYPE,
664                              &err);
665   opus_encoder_ctl (enc,
666                     OPUS_SET_PACKET_LOSS_PERC (CONV_OPUS_PACKET_LOSS_PERCENTAGE));
667   opus_encoder_ctl (enc,
668                     OPUS_SET_COMPLEXITY (CONV_OPUS_ENCODING_COMPLEXITY));
669   opus_encoder_ctl (enc,
670                     OPUS_SET_INBAND_FEC (CONV_OPUS_INBAND_FEC));
671   opus_encoder_ctl (enc,
672                     OPUS_SET_SIGNAL (CONV_OPUS_SIGNAL));
673 }
674
675
676 static void
677 ogg_init ()
678 {
679   int serialno;
680   struct OpusHeadPacket headpacket;
681   struct OpusCommentsPacket *commentspacket;
682   size_t commentspacket_len;
683
684   serialno = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
685                                        0x7FFFFFFF);
686   /*Initialize Ogg stream struct*/
687   if (-1 == ogg_stream_init (&os, serialno))
688   {
689     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
690                 _("ogg_stream_init() failed.\n"));
691     exit (3);
692   }
693
694   packet_id = 0;
695
696   /*Write header*/
697   {
698     ogg_packet op;
699     ogg_page og;
700     const char *opusver;
701     int vendor_length;
702
703     GNUNET_memcpy (headpacket.magic, "OpusHead", 8);
704     headpacket.version = 1;
705     headpacket.channels = CHANNELS;
706     headpacket.preskip = GNUNET_htole16 (0);
707     headpacket.sampling_rate = GNUNET_htole32 (SAMPLING_RATE);
708     headpacket.gain = GNUNET_htole16 (0);
709     headpacket.channel_mapping = 0; /* Mono or stereo */
710
711     op.packet = (unsigned char *) &headpacket;
712     op.bytes = sizeof (headpacket);
713     op.b_o_s = 1;
714     op.e_o_s = 0;
715     op.granulepos = 0;
716     op.packetno = packet_id++;
717     ogg_stream_packetin (&os, &op);
718
719     /* Head packet must be alone on its page */
720     while (ogg_stream_flush (&os, &og))
721     {
722       write_page (&og);
723     }
724
725     commentspacket_len = sizeof (*commentspacket);
726     opusver = opus_get_version_string ();
727     vendor_length = strlen (opusver);
728     commentspacket_len += vendor_length;
729     commentspacket_len += sizeof (uint32_t);
730
731     commentspacket = (struct OpusCommentsPacket *) malloc (commentspacket_len);
732     if (NULL == commentspacket)
733     {
734       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
735                   _("Failed to allocate %u bytes for second packet\n"),
736                   (unsigned int) commentspacket_len);
737       exit (5);
738     }
739
740     GNUNET_memcpy (commentspacket->magic, "OpusTags", 8);
741     commentspacket->vendor_length = GNUNET_htole32 (vendor_length);
742     GNUNET_memcpy (&commentspacket[1], opusver, vendor_length);
743     *(uint32_t *) &((char *) &commentspacket[1])[vendor_length] = \
744         GNUNET_htole32 (0); /* no tags */
745
746     op.packet = (unsigned char *) commentspacket;
747     op.bytes = commentspacket_len;
748     op.b_o_s = 0;
749     op.e_o_s = 0;
750     op.granulepos = 0;
751     op.packetno = packet_id++;
752     ogg_stream_packetin (&os, &op);
753
754     /* Comment packets must not be mixed with audio packets on their pages */
755     while (ogg_stream_flush (&os, &og))
756     {
757       write_page (&og);
758     }
759
760     free (commentspacket);
761   }
762 }
763
764 /**
765  * The main function for the record helper.
766  *
767  * @param argc number of arguments from the command line
768  * @param argv command line arguments
769  * @return 0 ok, 1 on error
770  */
771 int
772 main (int argc,
773       char *argv[])
774 {
775   (void) argc;
776   (void) argv;
777   GNUNET_assert (GNUNET_OK ==
778                  GNUNET_log_setup ("gnunet-helper-audio-record",
779                                    "WARNING",
780                                    NULL));
781   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
782               "Audio source starts\n");
783   audio_message = GNUNET_malloc (UINT16_MAX);
784   audio_message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
785
786 #ifdef DEBUG_RECORD_PURE_OGG
787   dump_pure_ogg = getenv ("GNUNET_RECORD_PURE_OGG") ? 1 : 0;
788 #endif
789   ogg_init ();
790   opus_init ();
791   pa_init ();
792   return 0;
793 }