GNUnet 0.21.1
gnunet-helper-audio-record.c File Reference

program to record audio data from the microphone More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_protocols.h"
#include "conversation.h"
#include "gnunet_constants.h"
#include "gnunet_core_service.h"
#include <pulse/simple.h>
#include <pulse/error.h>
#include <pulse/rtclock.h>
#include <pulse/pulseaudio.h>
#include <opus/opus.h>
#include <opus/opus_types.h>
#include <ogg/ogg.h>
Include dependency graph for gnunet-helper-audio-record.c:

Go to the source code of this file.

Data Structures

struct  OpusHeadPacket
 
struct  OpusCommentsPacket
 

Macros

#define DEBUG_RECORD_PURE_OGG   1
 
#define SAMPLING_RATE   48000
 Sampling rate. More...
 
#define FRAME_SIZE_MS   40
 How many ms of audio to buffer before encoding them. More...
 
#define FRAME_SIZE   (SAMPLING_RATE / 1000 * FRAME_SIZE_MS)
 How many samples to buffer before encoding them. More...
 
#define PAGE_WATERLINE   800
 Pages are committed when their size goes over this value. More...
 
#define MAX_PAYLOAD_BYTES   1024
 Maximum length of opus payload. More...
 
#define CHANNELS   1
 Number of channels. More...
 
#define CONV_OPUS_PACKET_LOSS_PERCENTAGE   1
 Configures the encoder's expected packet loss percentage. More...
 
#define CONV_OPUS_ENCODING_COMPLEXITY   10
 Configures the encoder's computational complexity. More...
 
#define CONV_OPUS_INBAND_FEC   1
 Configures the encoder's use of inband forward error correction (FEC). More...
 
#define CONV_OPUS_SIGNAL   OPUS_SIGNAL_VOICE
 Configures the type of signal being encoded. More...
 
#define CONV_OPUS_APP_TYPE   OPUS_APPLICATION_VOIP
 Coding mode. More...
 

Functions

static void quit (int ret)
 Pulseaudio shutdown task. More...
 
static void write_data (const char *ptr, size_t msg_size)
 
static void write_page (ogg_page *og)
 
static void packetizer ()
 Creates OPUS packets from PCM data. More...
 
static void stream_read_callback (pa_stream *s, size_t length, void *userdata)
 Pulseaudio callback when new data is available. More...
 
static void exit_signal_callback (pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata)
 Exit callback for SIGTERM and SIGINT. More...
 
static void stream_state_callback (pa_stream *s, void *userdata)
 Pulseaudio stream state callback. More...
 
static void context_state_callback (pa_context *c, void *userdata)
 Pulseaudio context state callback. More...
 
static void pa_init ()
 Pulsaudio init. More...
 
static void opus_init ()
 OPUS init. More...
 
static void ogg_init ()
 
int main (int argc, char *argv[])
 The main function for the record helper. More...
 

Variables

static pa_sample_spec sample_spec
 Specification for recording. More...
 
static GNUNET_NETWORK_STRUCT_END pa_mainloop_api * mainloop_api
 Pulseaudio mainloop api. More...
 
static pa_mainloop * m
 Pulseaudio mainloop. More...
 
static pa_context * context
 Pulseaudio context. More...
 
static pa_stream * stream_in
 Pulseaudio recording stream. More...
 
static pa_io_event * stdio_event
 Pulseaudio io events. More...
 
static OpusEncoder * enc
 OPUS encoder. More...
 
static unsigned char * opus_data
 Buffer for encoded data. More...
 
static float * pcm_buffer
 PCM data buffer for one OPUS frame. More...
 
static int pcm_length
 Length of the pcm data needed for one OPUS frame. More...
 
static char * transmit_buffer
 Audio buffer. More...
 
static size_t transmit_buffer_length
 Length of audio buffer. More...
 
static size_t transmit_buffer_index
 Read index for transmit buffer. More...
 
static struct AudioMessageaudio_message
 Audio message skeleton. More...
 
static ogg_stream_state os
 Ogg muxer state. More...
 
static int32_t packet_id
 Ogg packet id. More...
 
static int64_t enc_granulepos
 Ogg granule for current packet. More...
 
static int dump_pure_ogg
 1 to not to write GNUnet message headers, producing pure playable ogg output More...
 

Detailed Description

program to record audio data from the microphone

Author
Siomon Dieterle
Andreas Fuchs
Christian Grothoff

Definition in file gnunet-helper-audio-record.c.

Macro Definition Documentation

◆ DEBUG_RECORD_PURE_OGG

#define DEBUG_RECORD_PURE_OGG   1

Definition at line 43 of file gnunet-helper-audio-record.c.

◆ SAMPLING_RATE

#define SAMPLING_RATE   48000

Sampling rate.

Definition at line 48 of file gnunet-helper-audio-record.c.

◆ FRAME_SIZE_MS

#define FRAME_SIZE_MS   40

How many ms of audio to buffer before encoding them.

Possible values: 60, 40, 20, 10, 5, 2.5

Definition at line 55 of file gnunet-helper-audio-record.c.

◆ FRAME_SIZE

#define FRAME_SIZE   (SAMPLING_RATE / 1000 * FRAME_SIZE_MS)

How many samples to buffer before encoding them.

Definition at line 60 of file gnunet-helper-audio-record.c.

◆ PAGE_WATERLINE

#define PAGE_WATERLINE   800

Pages are committed when their size goes over this value.

Note that in practice we flush pages VERY often (every frame), which means that pages NEVER really get to be this big. With one-packet-per-page, pages are roughly 100-300 bytes each.

This value is chosen to make MAX_PAYLOAD_BYTES=1024 fit into a single page.

Definition at line 71 of file gnunet-helper-audio-record.c.

◆ MAX_PAYLOAD_BYTES

#define MAX_PAYLOAD_BYTES   1024

Maximum length of opus payload.

Definition at line 76 of file gnunet-helper-audio-record.c.

◆ CHANNELS

#define CHANNELS   1

Number of channels.

Definition at line 81 of file gnunet-helper-audio-record.c.

◆ CONV_OPUS_PACKET_LOSS_PERCENTAGE

#define CONV_OPUS_PACKET_LOSS_PERCENTAGE   1

Configures the encoder's expected packet loss percentage.

Higher values will trigger progressively more loss resistant behavior in the encoder at the expense of quality at a given bitrate in the lossless case, but greater quality under loss.

Definition at line 90 of file gnunet-helper-audio-record.c.

◆ CONV_OPUS_ENCODING_COMPLEXITY

#define CONV_OPUS_ENCODING_COMPLEXITY   10

Configures the encoder's computational complexity.

The supported range is 0-10 inclusive with 10 representing the highest complexity.

Definition at line 98 of file gnunet-helper-audio-record.c.

◆ CONV_OPUS_INBAND_FEC

#define CONV_OPUS_INBAND_FEC   1

Configures the encoder's use of inband forward error correction (FEC).

Note: This is only applicable to the LPC layer.

Definition at line 105 of file gnunet-helper-audio-record.c.

◆ CONV_OPUS_SIGNAL

#define CONV_OPUS_SIGNAL   OPUS_SIGNAL_VOICE

Configures the type of signal being encoded.

This is a hint which helps the encoder's mode selection.

Possible values: OPUS_AUTO - (default) Encoder detects the type automatically. OPUS_SIGNAL_VOICE - Bias thresholds towards choosing LPC or Hybrid modes. OPUS_SIGNAL_MUSIC - Bias thresholds towards choosing MDCT modes.

Definition at line 117 of file gnunet-helper-audio-record.c.

◆ CONV_OPUS_APP_TYPE

#define CONV_OPUS_APP_TYPE   OPUS_APPLICATION_VOIP

Coding mode.

Possible values: OPUS_APPLICATION_VOIP - gives best quality at a given bitrate for voice signals. It enhances the input signal by high-pass filtering and emphasizing formants and harmonics. Optionally it includes in-band forward error correction to protect against packet loss. Use this mode for typical VoIP applications. Because of the enhancement, even at high bitrates the output may sound different from the input. OPUS_APPLICATION_AUDIO - gives best quality at a given bitrate for most non-voice signals like music. Use this mode for music and mixed (music/voice) content, broadcast, and applications requiring less than 15 ms of coding delay. OPUS_APPLICATION_RESTRICTED_LOWDELAY - configures low-delay mode that disables the speech-optimized mode in exchange for slightly reduced delay. This mode can only be set on an newly initialized or freshly reset encoder because it changes the codec delay.

Definition at line 138 of file gnunet-helper-audio-record.c.

Function Documentation

◆ quit()

static void quit ( int  ret)
static

Pulseaudio shutdown task.

Definition at line 270 of file gnunet-helper-audio-record.c.

271{
273 ret);
274 exit (ret);
275}
static int ret
Final status code.
Definition: gnunet-arm.c:94
static GNUNET_NETWORK_STRUCT_END pa_mainloop_api * mainloop_api
Pulseaudio mainloop api.

References mainloop_api, and ret.

Referenced by context_state_callback(), exit_signal_callback(), packetizer(), stream_read_callback(), stream_state_callback(), and write_data().

Here is the caller graph for this function:

◆ write_data()

static void write_data ( const char *  ptr,
size_t  msg_size 
)
static

Definition at line 279 of file gnunet-helper-audio-record.c.

281{
282 ssize_t ret;
283 size_t off;
284
285 off = 0;
286 while (off < msg_size)
287 {
288 ret = write (STDOUT_FILENO,
289 &ptr[off],
290 msg_size - off);
291 if (0 >= ret)
292 {
293 if (-1 == ret)
295 "write");
296 quit (2);
297 }
298 off += ret;
299 }
300}
static void quit(int ret)
Pulseaudio shutdown task.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_ERROR

References GNUNET_ERROR_TYPE_ERROR, GNUNET_log_strerror, quit(), and ret.

Referenced by write_page().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_page()

static void write_page ( ogg_page *  og)
static

Definition at line 304 of file gnunet-helper-audio-record.c.

305{
306 static unsigned long long toff;
307 size_t msg_size;
308
309 msg_size = sizeof(struct AudioMessage) + og->header_len + og->body_len;
310 audio_message->header.size = htons ((uint16_t) msg_size);
311 GNUNET_memcpy (&audio_message[1], og->header, og->header_len);
312 GNUNET_memcpy (((char *) &audio_message[1]) + og->header_len, og->body,
313 og->body_len);
314
315 toff += msg_size;
317 "Sending %u bytes of audio data (total: %llu)\n",
318 (unsigned int) msg_size,
319 toff);
320#ifdef DEBUG_RECORD_PURE_OGG
321 if (dump_pure_ogg)
322 write_data ((const char *) &audio_message[1],
323 og->header_len + og->body_len);
324 else
325#endif
326 write_data ((const char *) audio_message,
327 msg_size);
328}
static int dump_pure_ogg
1 to not to write GNUnet message headers, producing pure playable ogg output
static struct AudioMessage * audio_message
Audio message skeleton.
static void write_data(const char *ptr, size_t msg_size)
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_ERROR_TYPE_DEBUG
Message to transmit the audio (between client and helpers).
Definition: conversation.h:59
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO.
Definition: conversation.h:63
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.

References audio_message, dump_pure_ogg, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, AudioMessage::header, GNUNET_MessageHeader::size, and write_data().

Referenced by ogg_init(), and packetizer().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ packetizer()

static void packetizer ( )
static

Creates OPUS packets from PCM data.

Definition at line 335 of file gnunet-helper-audio-record.c.

336{
337 char *nbuf;
338 size_t new_size;
339 int32_t len;
340 ogg_packet op;
341 ogg_page og;
342
344 {
347 pcm_length);
349 len =
350 opus_encode_float (enc, pcm_buffer, FRAME_SIZE, opus_data,
352
353 if (len < 0)
354 {
356 _ ("opus_encode_float() failed: %s. Aborting\n"),
357 opus_strerror (len));
358 quit (5);
359 }
360 if (((uint32_t) len) > UINT16_MAX - sizeof(struct AudioMessage))
361 {
362 GNUNET_break (0);
363 continue;
364 }
365
366 /* As per OggOpus spec, granule is calculated as if the audio
367 had 48kHz sampling rate. */
369
370 op.packet = (unsigned char *) opus_data;
371 op.bytes = len;
372 op.b_o_s = 0;
373 op.e_o_s = 0;
374 op.granulepos = enc_granulepos;
375 op.packetno = packet_id++;
376 ogg_stream_packetin (&os, &op);
377
378 while (ogg_stream_flush_fill (&os, &og, PAGE_WATERLINE))
379 {
380 if (((unsigned long long) og.header_len)
381 + ((unsigned long long) og.body_len) >
382 UINT16_MAX - sizeof(struct AudioMessage))
383 {
384 GNUNET_assert (0);
385 continue;
386 }
387 write_page (&og);
388 }
389 }
390
392 if (0 != new_size)
393 {
394 nbuf = pa_xmalloc (new_size);
395 memmove (nbuf,
397 new_size);
398 pa_xfree (transmit_buffer);
399 transmit_buffer = nbuf;
400 }
401 else
402 {
403 pa_xfree (transmit_buffer);
404 transmit_buffer = NULL;
405 }
407 transmit_buffer_length = new_size;
408}
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
#define SAMPLING_RATE
Sampling rate.
#define MAX_PAYLOAD_BYTES
Maximum length of opus payload.
static size_t transmit_buffer_index
Read index for transmit buffer.
#define PAGE_WATERLINE
Pages are committed when their size goes over this value.
static float * pcm_buffer
PCM data buffer for one OPUS frame.
static size_t transmit_buffer_length
Length of audio buffer.
static char * transmit_buffer
Audio buffer.
static void write_page(ogg_page *og)
static unsigned char * opus_data
Buffer for encoded data.
static OpusEncoder * enc
OPUS encoder.
static int32_t packet_id
Ogg packet id.
static ogg_stream_state os
Ogg muxer state.
#define FRAME_SIZE
How many samples to buffer before encoding them.
static int64_t enc_granulepos
Ogg granule for current packet.
static int pcm_length
Length of the pcm data needed for one OPUS frame.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define _(String)
GNU gettext support macro.
Definition: platform.h:178

References _, enc, enc_granulepos, FRAME_SIZE, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_memcpy, MAX_PAYLOAD_BYTES, op, opus_data, os, packet_id, PAGE_WATERLINE, pcm_buffer, pcm_length, quit(), SAMPLING_RATE, transmit_buffer, transmit_buffer_index, transmit_buffer_length, and write_page().

Referenced by stream_read_callback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stream_read_callback()

static void stream_read_callback ( pa_stream *  s,
size_t  length,
void *  userdata 
)
static

Pulseaudio callback when new data is available.

Definition at line 415 of file gnunet-helper-audio-record.c.

418{
419 const void *data;
420
421 (void) userdata;
423 "Got %u/%d bytes of PCM data\n",
424 (unsigned int) length,
425 pcm_length);
426
427 GNUNET_assert (NULL != s);
428 GNUNET_assert (length > 0);
429 if (stdio_event)
430 mainloop_api->io_enable (stdio_event, PA_IO_EVENT_OUTPUT);
431
432 if (pa_stream_peek (s, (const void **) &data, &length) < 0)
433 {
435 _ ("pa_stream_peek() failed: %s\n"),
436 pa_strerror (pa_context_errno (context)));
437 quit (1);
438 return;
439 }
440 GNUNET_assert (NULL != data);
441 GNUNET_assert (length > 0);
442 if (NULL != transmit_buffer)
443 {
444 transmit_buffer = pa_xrealloc (transmit_buffer,
445 transmit_buffer_length + length);
447 data,
448 length);
449 transmit_buffer_length += length;
450 }
451 else
452 {
453 transmit_buffer = pa_xmalloc (length);
455 transmit_buffer_length = length;
457 }
458 pa_stream_drop (s);
459 packetizer ();
460}
static char * data
The data to insert into the dht.
static pa_context * context
Pulseaudio context.
static void packetizer()
Creates OPUS packets from PCM data.
static pa_io_event * stdio_event
Pulseaudio io events.

References _, context, data, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_memcpy, mainloop_api, packetizer(), pcm_length, quit(), stdio_event, transmit_buffer, transmit_buffer_index, and transmit_buffer_length.

Referenced by context_state_callback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ exit_signal_callback()

static void exit_signal_callback ( pa_mainloop_api *  m,
pa_signal_event *  e,
int  sig,
void *  userdata 
)
static

Exit callback for SIGTERM and SIGINT.

Definition at line 467 of file gnunet-helper-audio-record.c.

471{
472 (void) m;
473 (void) e;
474 (void) sig;
475 (void) userdata;
477 _ ("Got signal, exiting.\n"));
478 quit (1);
479}
static pa_mainloop * m
Pulseaudio mainloop.
@ GNUNET_ERROR_TYPE_INFO

References _, GNUNET_ERROR_TYPE_INFO, GNUNET_log, m, and quit().

Referenced by pa_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stream_state_callback()

static void stream_state_callback ( pa_stream *  s,
void *  userdata 
)
static

Pulseaudio stream state callback.

Definition at line 486 of file gnunet-helper-audio-record.c.

488{
489 (void) userdata;
490 GNUNET_assert (NULL != s);
491 switch (pa_stream_get_state (s))
492 {
493 case PA_STREAM_CREATING:
494 case PA_STREAM_TERMINATED:
495 break;
496
497 case PA_STREAM_READY:
498 {
499 const pa_buffer_attr *a;
500 char cmt[PA_CHANNEL_MAP_SNPRINT_MAX];
501 char sst[PA_SAMPLE_SPEC_SNPRINT_MAX];
502
504 _ ("Stream successfully created.\n"));
505
506 if (! (a = pa_stream_get_buffer_attr (s)))
507 {
509 _ ("pa_stream_get_buffer_attr() failed: %s\n"),
510 pa_strerror (pa_context_errno
511 (pa_stream_get_context (s))));
512 }
513 else
514 {
516 _ ("Buffer metrics: maxlength=%u, fragsize=%u\n"),
517 a->maxlength, a->fragsize);
518 }
520 _ ("Using sample spec '%s', channel map '%s'.\n"),
521 pa_sample_spec_snprint (sst, sizeof(sst),
522 pa_stream_get_sample_spec (s)),
523 pa_channel_map_snprint (cmt, sizeof(cmt),
524 pa_stream_get_channel_map (s)));
525
527 _ ("Connected to device %s (%u, %ssuspended).\n"),
528 pa_stream_get_device_name (s),
529 pa_stream_get_device_index (s),
530 pa_stream_is_suspended (s) ? "" : "not ");
531 }
532 break;
533
534 case PA_STREAM_FAILED:
535 default:
537 _ ("Stream error: %s\n"),
538 pa_strerror (pa_context_errno (pa_stream_get_context (s))));
539 quit (1);
540 }
541}

References _, GNUNET_assert, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_log, and quit().

Referenced by context_state_callback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ context_state_callback()

static void context_state_callback ( pa_context *  c,
void *  userdata 
)
static

Pulseaudio context state callback.

Definition at line 548 of file gnunet-helper-audio-record.c.

550{
551 (void) userdata;
552 GNUNET_assert (c);
553
554 switch (pa_context_get_state (c))
555 {
556 case PA_CONTEXT_CONNECTING:
557 case PA_CONTEXT_AUTHORIZING:
558 case PA_CONTEXT_SETTING_NAME:
559 break;
560
561 case PA_CONTEXT_READY:
562 {
563 int r;
564 pa_buffer_attr na;
565
568 _ ("Connection established.\n"));
569 if (! (stream_in =
570 pa_stream_new (c, "GNUNET_VoIP recorder", &sample_spec, NULL)))
571 {
573 _ ("pa_stream_new() failed: %s\n"),
574 pa_strerror (pa_context_errno (c)));
575 goto fail;
576 }
577 pa_stream_set_state_callback (stream_in, &stream_state_callback, NULL);
578 pa_stream_set_read_callback (stream_in, &stream_read_callback, NULL);
579 memset (&na, 0, sizeof(na));
580 na.maxlength = UINT32_MAX;
581 na.fragsize = pcm_length;
582 if ((r = pa_stream_connect_record (stream_in, NULL, &na,
583 PA_STREAM_ADJUST_LATENCY)) < 0)
584 {
586 _ ("pa_stream_connect_record() failed: %s\n"),
587 pa_strerror (pa_context_errno (c)));
588 goto fail;
589 }
590
591 break;
592 }
593
594 case PA_CONTEXT_TERMINATED:
595 quit (0);
596 break;
597
598 case PA_CONTEXT_FAILED:
599 default:
601 _ ("Connection failure: %s\n"),
602 pa_strerror (pa_context_errno (c)));
603 goto fail;
604 }
605 return;
606
607fail:
608 quit (1);
609}
static pa_stream * stream_in
Pulseaudio recording stream.
static void stream_read_callback(pa_stream *s, size_t length, void *userdata)
Pulseaudio callback when new data is available.
static void stream_state_callback(pa_stream *s, void *userdata)
Pulseaudio stream state callback.
static pa_sample_spec sample_spec
Specification for recording.

References _, GNUNET_assert, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_log, pcm_length, quit(), sample_spec, stream_in, stream_read_callback(), and stream_state_callback().

Referenced by pa_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pa_init()

static void pa_init ( )
static

Pulsaudio init.

Definition at line 616 of file gnunet-helper-audio-record.c.

617{
618 int r;
619 int i;
620
621 if (! pa_sample_spec_valid (&sample_spec))
622 {
624 _ ("Wrong Spec\n"));
625 }
626 /* set up main record loop */
627 if (! (m = pa_mainloop_new ()))
628 {
630 _ ("pa_mainloop_new() failed.\n"));
631 }
632 mainloop_api = pa_mainloop_get_api (m);
633
634 /* listen to signals */
635 r = pa_signal_init (mainloop_api);
636 GNUNET_assert (r == 0);
637 pa_signal_new (SIGINT, &exit_signal_callback, NULL);
638 pa_signal_new (SIGTERM, &exit_signal_callback, NULL);
639
640 /* connect to the main pulseaudio context */
641
642 if (! (context = pa_context_new (mainloop_api, "GNUNET VoIP")))
643 {
645 _ ("pa_context_new() failed.\n"));
646 }
647 pa_context_set_state_callback (context, &context_state_callback, NULL);
648 if (pa_context_connect (context, NULL, 0, NULL) < 0)
649 {
651 _ ("pa_context_connect() failed: %s\n"),
652 pa_strerror (pa_context_errno (context)));
653 }
654 if (pa_mainloop_run (m, &i) < 0)
655 {
657 _ ("pa_mainloop_run() failed.\n"));
658 }
659}
static void context_state_callback(pa_context *c, void *userdata)
Pulseaudio context state callback.
static void exit_signal_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata)
Exit callback for SIGTERM and SIGINT.

References _, context, context_state_callback(), exit_signal_callback(), GNUNET_assert, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, m, mainloop_api, and sample_spec.

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ opus_init()

static void opus_init ( )
static

OPUS init.

Definition at line 666 of file gnunet-helper-audio-record.c.

667{
668 int err;
669
670 pcm_length = FRAME_SIZE * CHANNELS * sizeof(float);
671 pcm_buffer = pa_xmalloc (pcm_length);
673 enc = opus_encoder_create (SAMPLING_RATE,
674 CHANNELS,
676 &err);
677 opus_encoder_ctl (enc,
678 OPUS_SET_PACKET_LOSS_PERC (
680 opus_encoder_ctl (enc,
681 OPUS_SET_COMPLEXITY (CONV_OPUS_ENCODING_COMPLEXITY));
682 opus_encoder_ctl (enc,
683 OPUS_SET_INBAND_FEC (CONV_OPUS_INBAND_FEC));
684 opus_encoder_ctl (enc,
685 OPUS_SET_SIGNAL (CONV_OPUS_SIGNAL));
686}
#define CONV_OPUS_INBAND_FEC
Configures the encoder's use of inband forward error correction (FEC).
#define CONV_OPUS_SIGNAL
Configures the type of signal being encoded.
#define CHANNELS
Number of channels.
#define CONV_OPUS_APP_TYPE
Coding mode.
#define CONV_OPUS_ENCODING_COMPLEXITY
Configures the encoder's computational complexity.
#define CONV_OPUS_PACKET_LOSS_PERCENTAGE
Configures the encoder's expected packet loss percentage.
#define GNUNET_malloc(size)
Wrapper around malloc.

References CHANNELS, CONV_OPUS_APP_TYPE, CONV_OPUS_ENCODING_COMPLEXITY, CONV_OPUS_INBAND_FEC, CONV_OPUS_PACKET_LOSS_PERCENTAGE, CONV_OPUS_SIGNAL, enc, FRAME_SIZE, GNUNET_malloc, MAX_PAYLOAD_BYTES, opus_data, pcm_buffer, pcm_length, and SAMPLING_RATE.

Referenced by main().

Here is the caller graph for this function:

◆ ogg_init()

static void ogg_init ( )
static

Definition at line 690 of file gnunet-helper-audio-record.c.

691{
692 int serialno;
693 struct OpusHeadPacket headpacket;
694 struct OpusCommentsPacket *commentspacket;
695 size_t commentspacket_len;
696
698 0x7FFFFFFF);
699 /*Initialize Ogg stream struct*/
700 if (-1 == ogg_stream_init (&os, serialno))
701 {
703 _ ("ogg_stream_init() failed.\n"));
704 exit (3);
705 }
706
707 packet_id = 0;
708
709 /*Write header*/
710 {
711 ogg_packet op;
712 ogg_page og;
713 const char *opusver;
714 int vendor_length;
715
716 GNUNET_memcpy (headpacket.magic, "OpusHead", 8);
717 headpacket.version = 1;
718 headpacket.channels = CHANNELS;
719 headpacket.preskip = GNUNET_htole16 (0);
720 headpacket.sampling_rate = GNUNET_htole32 (SAMPLING_RATE);
721 headpacket.gain = GNUNET_htole16 (0);
722 headpacket.channel_mapping = 0; /* Mono or stereo */
723
724 op.packet = (unsigned char *) &headpacket;
725 op.bytes = sizeof(headpacket);
726 op.b_o_s = 1;
727 op.e_o_s = 0;
728 op.granulepos = 0;
729 op.packetno = packet_id++;
730 ogg_stream_packetin (&os, &op);
731
732 /* Head packet must be alone on its page */
733 while (ogg_stream_flush (&os, &og))
734 {
735 write_page (&og);
736 }
737
738 commentspacket_len = sizeof(*commentspacket);
739 opusver = opus_get_version_string ();
740 vendor_length = strlen (opusver);
741 commentspacket_len += vendor_length;
742 commentspacket_len += sizeof(uint32_t);
743
744 commentspacket = (struct OpusCommentsPacket *) malloc (commentspacket_len);
745 if (NULL == commentspacket)
746 {
748 _ ("Failed to allocate %u bytes for second packet\n"),
749 (unsigned int) commentspacket_len);
750 exit (5);
751 }
752
753 GNUNET_memcpy (commentspacket->magic, "OpusTags", 8);
754 commentspacket->vendor_length = GNUNET_htole32 (vendor_length);
755 GNUNET_memcpy (&commentspacket[1], opusver, vendor_length);
756 *(uint32_t *) &((char *) &commentspacket[1])[vendor_length] = \
757 GNUNET_htole32 (0); /* no tags */
758
759 op.packet = (unsigned char *) commentspacket;
760 op.bytes = commentspacket_len;
761 op.b_o_s = 0;
762 op.e_o_s = 0;
763 op.granulepos = 0;
764 op.packetno = packet_id++;
765 ogg_stream_packetin (&os, &op);
766
767 /* Comment packets must not be mixed with audio packets on their pages */
768 while (ogg_stream_flush (&os, &og))
769 {
770 write_page (&og);
771 }
772
773 free (commentspacket);
774 }
775}
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_STRONG
High-quality operations are desired.
#define GNUNET_htole32(x)
#define GNUNET_htole16(x)

References _, OpusHeadPacket::channel_mapping, OpusHeadPacket::channels, CHANNELS, OpusHeadPacket::gain, GNUNET_CRYPTO_QUALITY_STRONG, GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_ERROR, GNUNET_htole16, GNUNET_htole32, GNUNET_log, GNUNET_memcpy, OpusHeadPacket::magic, OpusCommentsPacket::magic, op, os, packet_id, OpusHeadPacket::preskip, OpusHeadPacket::sampling_rate, SAMPLING_RATE, OpusCommentsPacket::vendor_length, OpusHeadPacket::version, and write_page().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *  argv[] 
)

The main function for the record helper.

Parameters
argcnumber of arguments from the command line
argvcommand line arguments
Returns
0 ok, 1 on error

Definition at line 786 of file gnunet-helper-audio-record.c.

788{
789 (void) argc;
790 (void) argv;
792 GNUNET_log_setup ("gnunet-helper-audio-record",
793 "WARNING",
794 NULL));
796 "Audio source starts\n");
797 audio_message = GNUNET_malloc (UINT16_MAX);
799
800#ifdef DEBUG_RECORD_PURE_OGG
801 dump_pure_ogg = getenv ("GNUNET_RECORD_PURE_OGG") ? 1 : 0;
802#endif
803 ogg_init ();
804 opus_init ();
805 pa_init ();
806 return 0;
807}
char * getenv()
static void pa_init()
Pulsaudio init.
static void ogg_init()
static void opus_init()
OPUS init.
@ GNUNET_OK
enum GNUNET_GenericReturnValue GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO
Message to transmit the audio between helper and speaker/microphone library.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.

References audio_message, dump_pure_ogg, getenv(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_log_setup(), GNUNET_malloc, GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO, GNUNET_OK, AudioMessage::header, ogg_init(), opus_init(), pa_init(), and GNUNET_MessageHeader::type.

Here is the call graph for this function:

Variable Documentation

◆ sample_spec

pa_sample_spec sample_spec
static
Initial value:
= {
.format = PA_SAMPLE_FLOAT32LE,
.rate = 48000 ,
.channels = 1
}

Specification for recording.

May change in the future to spec negotiation.

Definition at line 143 of file gnunet-helper-audio-record.c.

Referenced by context_state_callback(), and pa_init().

◆ mainloop_api

GNUNET_NETWORK_STRUCT_END pa_mainloop_api* mainloop_api
static

Pulseaudio mainloop api.

Definition at line 181 of file gnunet-helper-audio-record.c.

Referenced by pa_init(), quit(), and stream_read_callback().

◆ m

pa_mainloop* m
static

Pulseaudio mainloop.

Definition at line 186 of file gnunet-helper-audio-record.c.

Referenced by exit_signal_callback(), and pa_init().

◆ context

pa_context* context
static

Pulseaudio context.

Definition at line 191 of file gnunet-helper-audio-record.c.

Referenced by pa_init(), and stream_read_callback().

◆ stream_in

pa_stream* stream_in
static

Pulseaudio recording stream.

Definition at line 196 of file gnunet-helper-audio-record.c.

Referenced by context_state_callback().

◆ stdio_event

pa_io_event* stdio_event
static

Pulseaudio io events.

Definition at line 201 of file gnunet-helper-audio-record.c.

Referenced by stream_read_callback().

◆ enc

◆ opus_data

unsigned char* opus_data
static

Buffer for encoded data.

Definition at line 211 of file gnunet-helper-audio-record.c.

Referenced by opus_init(), and packetizer().

◆ pcm_buffer

float* pcm_buffer
static

PCM data buffer for one OPUS frame.

Definition at line 216 of file gnunet-helper-audio-record.c.

Referenced by opus_init(), and packetizer().

◆ pcm_length

int pcm_length
static

Length of the pcm data needed for one OPUS frame.

Definition at line 221 of file gnunet-helper-audio-record.c.

Referenced by context_state_callback(), opus_init(), packetizer(), and stream_read_callback().

◆ transmit_buffer

char* transmit_buffer
static

Audio buffer.

Definition at line 226 of file gnunet-helper-audio-record.c.

Referenced by packetizer(), and stream_read_callback().

◆ transmit_buffer_length

size_t transmit_buffer_length
static

Length of audio buffer.

Definition at line 231 of file gnunet-helper-audio-record.c.

Referenced by packetizer(), and stream_read_callback().

◆ transmit_buffer_index

size_t transmit_buffer_index
static

Read index for transmit buffer.

Definition at line 236 of file gnunet-helper-audio-record.c.

Referenced by packetizer(), and stream_read_callback().

◆ audio_message

struct AudioMessage* audio_message
static

Audio message skeleton.

Definition at line 241 of file gnunet-helper-audio-record.c.

Referenced by main(), and write_page().

◆ os

ogg_stream_state os
static

Ogg muxer state.

Definition at line 246 of file gnunet-helper-audio-record.c.

Referenced by ogg_init(), and packetizer().

◆ packet_id

int32_t packet_id
static

Ogg packet id.

Definition at line 251 of file gnunet-helper-audio-record.c.

Referenced by ogg_init(), and packetizer().

◆ enc_granulepos

int64_t enc_granulepos
static

Ogg granule for current packet.

Definition at line 256 of file gnunet-helper-audio-record.c.

Referenced by packetizer().

◆ dump_pure_ogg

int dump_pure_ogg
static

1 to not to write GNUnet message headers, producing pure playable ogg output

Definition at line 263 of file gnunet-helper-audio-record.c.

Referenced by main(), and write_page().