static void aout_DecSilence (audio_output_t *aout, mtime_t length, mtime_t pts) { aout_owner_t *owner = aout_owner (aout); const audio_sample_format_t *fmt = &owner->mixer_format; size_t frames = (fmt->i_rate * length) / CLOCK_FREQ; block_t *block; if (AOUT_FMT_SPDIF(fmt)) block = block_Alloc (4 * frames); else block = block_Alloc (frames * fmt->i_bytes_per_frame); if (unlikely(block == NULL)) return; /* uho! */ msg_Dbg (aout, "inserting %zu zeroes", frames); memset (block->p_buffer, 0, block->i_buffer); block->i_nb_samples = frames; block->i_pts = pts; block->i_dts = pts; block->i_length = length; aout_OutputPlay (aout, block); }
/***************************************************************************** * Open: open the audio device (the digital sound processor) ***************************************************************************** * This function opens the DSP as a usual non-blocking write-only file, and * modifies the p_aout->p_sys->i_fd with the file's descriptor. *****************************************************************************/ static int Open( vlc_object_t *p_this ) { audio_output_t * p_aout = (audio_output_t *)p_this; struct aout_sys_t * p_sys; char * psz_device; vlc_value_t val; /* Allocate structure */ p_aout->sys = p_sys = malloc( sizeof( aout_sys_t ) ); if( p_sys == NULL ) return VLC_ENOMEM; /* Get device name */ if( (psz_device = var_InheritString( p_aout, "oss-audio-device" )) == NULL ) { msg_Err( p_aout, "no audio device specified (maybe /dev/dsp?)" ); free( p_sys ); return VLC_EGENERIC; } /* Open the sound device in non-blocking mode, because ALSA's OSS * emulation and some broken OSS drivers would make a blocking call * wait forever until the device is available. Since this breaks the * OSS spec, we immediately put it back to blocking mode if the * operation was successful. */ p_sys->i_fd = vlc_open( psz_device, O_WRONLY | O_NDELAY ); if( p_sys->i_fd < 0 ) { msg_Err( p_aout, "cannot open audio device (%s)", psz_device ); free( psz_device ); free( p_sys ); return VLC_EGENERIC; } /* if the opening was ok, put the device back in blocking mode */ fcntl( p_sys->i_fd, F_SETFL, fcntl( p_sys->i_fd, F_GETFL ) &~ FNDELAY ); free( psz_device ); p_aout->pf_play = aout_PacketPlay; p_aout->pf_pause = aout_PacketPause; p_aout->pf_flush = aout_PacketFlush; if ( var_Type( p_aout, "audio-device" ) == 0 ) Probe( p_aout ); var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL ); if ( var_Get( p_aout, "audio-device", &val ) < 0 ) /* Probe() has failed. */ goto error; if ( val.i_int == AOUT_VAR_SPDIF ) { p_aout->format.i_format = VLC_CODEC_SPDIFL; } else if ( val.i_int == AOUT_VAR_5_1 ) { p_aout->format.i_format = VLC_CODEC_S16N; p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; } else if ( val.i_int == AOUT_VAR_2F2R ) { p_aout->format.i_format = VLC_CODEC_S16N; p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; } else if ( val.i_int == AOUT_VAR_STEREO ) { p_aout->format.i_format = VLC_CODEC_S16N; p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; } else if ( val.i_int == AOUT_VAR_MONO ) { p_aout->format.i_format = VLC_CODEC_S16N; p_aout->format.i_physical_channels = AOUT_CHAN_CENTER; } else { /* This should not happen ! */ msg_Err( p_aout, "internal: can't find audio-device (%"PRId64")", val.i_int ); goto error; } var_TriggerCallback( p_aout, "intf-change" ); /* Reset the DSP device */ if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 ) { msg_Err( p_aout, "cannot reset OSS audio device" ); goto error; } /* Set the output format */ if ( AOUT_FMT_SPDIF( &p_aout->format ) ) { int i_format = AFMT_AC3; if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 || i_format != AFMT_AC3 ) { msg_Err( p_aout, "cannot reset OSS audio device" ); goto error; } p_aout->format.i_format = VLC_CODEC_SPDIFL; p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE; p_aout->format.i_frame_length = A52_FRAME_NB; aout_PacketInit( p_aout, &p_sys->packet, A52_FRAME_NB ); aout_VolumeNoneInit( p_aout ); } else { unsigned int i_format = AFMT_S16_NE; unsigned int i_frame_size, i_fragments; unsigned int i_rate; unsigned int i_nb_channels; audio_buf_info audio_buf; if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 ) { msg_Err( p_aout, "cannot set audio output format" ); goto error; } switch ( i_format ) { case AFMT_U8: p_aout->format.i_format = VLC_CODEC_U8; break; case AFMT_S8: p_aout->format.i_format = VLC_CODEC_S8; break; case AFMT_U16_LE: p_aout->format.i_format = VLC_CODEC_U16L; break; case AFMT_S16_LE: p_aout->format.i_format = VLC_CODEC_S16L; break; case AFMT_U16_BE: p_aout->format.i_format = VLC_CODEC_U16B; break; case AFMT_S16_BE: p_aout->format.i_format = VLC_CODEC_S16B; break; default: msg_Err( p_aout, "OSS fell back to an unknown format (%d)", i_format ); goto error; } i_nb_channels = aout_FormatNbChannels( &p_aout->format ); /* Set the number of channels */ if( ioctl( p_sys->i_fd, SNDCTL_DSP_CHANNELS, &i_nb_channels ) < 0 || i_nb_channels != aout_FormatNbChannels( &p_aout->format ) ) { msg_Err( p_aout, "cannot set number of audio channels (%s)", aout_FormatPrintChannels( &p_aout->format) ); goto error; } /* Set the output rate */ i_rate = p_aout->format.i_rate; if( ioctl( p_sys->i_fd, SNDCTL_DSP_SPEED, &i_rate ) < 0 ) { msg_Err( p_aout, "cannot set audio output rate (%i)", p_aout->format.i_rate ); goto error; } if( i_rate != p_aout->format.i_rate ) { p_aout->format.i_rate = i_rate; } /* Set the fragment size */ aout_FormatPrepare( &p_aout->format ); /* i_fragment = xxxxyyyy where: xxxx is fragtotal * 1 << yyyy is fragsize */ i_frame_size = ((uint64_t)p_aout->format.i_bytes_per_frame * p_aout->format.i_rate * 65536) / (48000 * 2 * 2) / FRAME_COUNT; i_fragments = 4; while( i_fragments < 12 && (1U << i_fragments) < i_frame_size ) { ++i_fragments; } i_fragments |= FRAME_COUNT << 16; if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFRAGMENT, &i_fragments ) < 0 ) { msg_Warn( p_aout, "cannot set fragment size (%.8x)", i_fragments ); } if( ioctl( p_sys->i_fd, SNDCTL_DSP_GETOSPACE, &audio_buf ) < 0 ) { msg_Err( p_aout, "cannot get fragment size" ); goto error; } /* Number of fragments actually allocated */ p_aout->sys->i_fragstotal = audio_buf.fragstotal; /* Maximum duration the soundcard's buffer can hold */ p_aout->sys->max_buffer_duration = (mtime_t)audio_buf.fragstotal * audio_buf.fragsize * 1000000 / p_aout->format.i_bytes_per_frame / p_aout->format.i_rate * p_aout->format.i_frame_length; aout_PacketInit( p_aout, &p_sys->packet, audio_buf.fragsize/p_aout->format.i_bytes_per_frame ); aout_VolumeSoftInit( p_aout ); } /* Create OSS thread and wait for its readiness. */ if( vlc_clone( &p_sys->thread, OSSThread, p_aout, VLC_THREAD_PRIORITY_OUTPUT ) ) { msg_Err( p_aout, "cannot create OSS thread (%m)" ); aout_PacketDestroy( p_aout ); goto error; } return VLC_SUCCESS; error: var_DelCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL ); close( p_sys->i_fd ); free( p_sys ); return VLC_EGENERIC; }
/***************************************************************************** * Probe: probe the audio device for available formats and channels *****************************************************************************/ static void Probe( audio_output_t * p_aout ) { struct aout_sys_t * p_sys = p_aout->sys; vlc_value_t val, text; int i_format, i_nb_channels; var_Create( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE ); text.psz_string = _("Audio Device"); var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL ); /* Test for multi-channel. */ #ifdef SNDCTL_DSP_GETCHANNELMASK if ( aout_FormatNbChannels( &p_aout->format ) > 2 ) { /* Check that the device supports this. */ int i_chanmask; /* Reset all. */ i_format = AFMT_S16_NE; if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 || ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 ) { msg_Err( p_aout, "cannot reset OSS audio device" ); var_Destroy( p_aout, "audio-device" ); return; } if ( ioctl( p_sys->i_fd, SNDCTL_DSP_GETCHANNELMASK, &i_chanmask ) == 0 ) { if ( !(i_chanmask & DSP_BIND_FRONT) ) { msg_Err( p_aout, "no front channels! (%x)", i_chanmask ); return; } if ( (i_chanmask & (DSP_BIND_SURR | DSP_BIND_CENTER_LFE)) && (p_aout->format.i_physical_channels == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE)) ) { val.i_int = AOUT_VAR_5_1; text.psz_string = (char*) "5.1"; var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); } if ( (i_chanmask & DSP_BIND_SURR) && (p_aout->format.i_physical_channels & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT)) ) { val.i_int = AOUT_VAR_2F2R; text.psz_string = _("2 Front 2 Rear"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); } } } #endif /* Reset all. */ i_format = AFMT_S16_NE; if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 || ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 ) { msg_Err( p_aout, "cannot reset OSS audio device" ); var_Destroy( p_aout, "audio-device" ); return; } /* Test for stereo. */ i_nb_channels = 2; if( ioctl( p_sys->i_fd, SNDCTL_DSP_CHANNELS, &i_nb_channels ) >= 0 && i_nb_channels == 2 ) { val.i_int = AOUT_VAR_STEREO; text.psz_string = _("Stereo"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); } /* Reset all. */ i_format = AFMT_S16_NE; if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 || ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 ) { msg_Err( p_aout, "cannot reset OSS audio device" ); var_Destroy( p_aout, "audio-device" ); return; } /* Test for mono. */ i_nb_channels = 1; if( ioctl( p_sys->i_fd, SNDCTL_DSP_CHANNELS, &i_nb_channels ) >= 0 && i_nb_channels == 1 ) { val.i_int = AOUT_VAR_MONO; text.psz_string = _("Mono"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); if ( p_aout->format.i_physical_channels == AOUT_CHAN_CENTER ) { var_Set( p_aout, "audio-device", val ); } } if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 ) { msg_Err( p_aout, "cannot reset OSS audio device" ); var_Destroy( p_aout, "audio-device" ); return; } /* Test for spdif. */ if ( AOUT_FMT_SPDIF( &p_aout->format ) ) { i_format = AFMT_AC3; if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) >= 0 && i_format == AFMT_AC3 ) { val.i_int = AOUT_VAR_SPDIF; text.psz_string = _("A/52 over S/PDIF"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); if( var_InheritBool( p_aout, "spdif" ) ) var_Set( p_aout, "audio-device", val ); } else if( var_InheritBool( p_aout, "spdif" ) ) { msg_Warn( p_aout, "S/PDIF not supported by card" ); } } }
/** Initializes an ALSA playback stream */ static int Open (vlc_object_t *obj) { audio_output_t *aout = (audio_output_t *)obj; /* Get device name */ char *device = var_InheritString (aout, "alsa-audio-device"); if (unlikely(device == NULL)) return VLC_ENOMEM; snd_pcm_format_t pcm_format; /* ALSA sample format */ vlc_fourcc_t fourcc = aout->format.i_format; bool spdif = false; switch (fourcc) { case VLC_CODEC_F64B: pcm_format = SND_PCM_FORMAT_FLOAT64_BE; break; case VLC_CODEC_F64L: pcm_format = SND_PCM_FORMAT_FLOAT64_LE; break; case VLC_CODEC_F32B: pcm_format = SND_PCM_FORMAT_FLOAT_BE; break; case VLC_CODEC_F32L: pcm_format = SND_PCM_FORMAT_FLOAT_LE; break; case VLC_CODEC_FI32: fourcc = VLC_CODEC_FL32; pcm_format = SND_PCM_FORMAT_FLOAT; break; case VLC_CODEC_S32B: pcm_format = SND_PCM_FORMAT_S32_BE; break; case VLC_CODEC_S32L: pcm_format = SND_PCM_FORMAT_S32_LE; break; case VLC_CODEC_S24B: pcm_format = SND_PCM_FORMAT_S24_3BE; break; case VLC_CODEC_S24L: pcm_format = SND_PCM_FORMAT_S24_3LE; break; case VLC_CODEC_U24B: pcm_format = SND_PCM_FORMAT_U24_3BE; break; case VLC_CODEC_U24L: pcm_format = SND_PCM_FORMAT_U24_3LE; break; case VLC_CODEC_S16B: pcm_format = SND_PCM_FORMAT_S16_BE; break; case VLC_CODEC_S16L: pcm_format = SND_PCM_FORMAT_S16_LE; break; case VLC_CODEC_U16B: pcm_format = SND_PCM_FORMAT_U16_BE; break; case VLC_CODEC_U16L: pcm_format = SND_PCM_FORMAT_U16_LE; break; case VLC_CODEC_S8: pcm_format = SND_PCM_FORMAT_S8; break; case VLC_CODEC_U8: pcm_format = SND_PCM_FORMAT_U8; break; default: if (AOUT_FMT_SPDIF(&aout->format)) spdif = var_InheritBool (aout, "spdif"); if (spdif) { fourcc = VLC_CODEC_SPDIFL; pcm_format = SND_PCM_FORMAT_S16; } else if (HAVE_FPU) { fourcc = VLC_CODEC_FL32; pcm_format = SND_PCM_FORMAT_FLOAT; } else { fourcc = VLC_CODEC_S16N; pcm_format = SND_PCM_FORMAT_S16; } } /* ALSA channels */ /* XXX: maybe this should be shared with other dumb outputs */ uint32_t map = var_InheritInteger (aout, "alsa-audio-channels"); map &= aout->format.i_physical_channels; if (unlikely(map == 0)) /* WTH? */ map = AOUT_CHANS_STEREO; unsigned channels = popcount (map); if (channels < aout_FormatNbChannels (&aout->format)) msg_Dbg (aout, "downmixing from %u to %u channels", aout_FormatNbChannels (&aout->format), channels); else msg_Dbg (aout, "keeping %u channels", channels); /* Choose the IEC device for S/PDIF output: if the device is overridden by the user then it will be the one. Otherwise we compute the default device based on the output format. */ if (spdif && !strcmp (device, "default")) { unsigned aes3; switch (aout->format.i_rate) { #define FS(freq) \ case freq: aes3 = IEC958_AES3_CON_FS_ ## freq; break; FS( 44100) /* def. */ FS( 48000) FS( 32000) FS( 22050) FS( 24000) FS( 88200) FS(768000) FS( 96000) FS(176400) FS(192000) #undef FS default: aes3 = IEC958_AES3_CON_FS_NOTID; break; } free (device); if (asprintf (&device, "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x", IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO, IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER, 0, aes3) == -1) return VLC_ENOMEM; }
/***************************************************************************** * Open: open a dummy audio device *****************************************************************************/ static int Open( vlc_object_t * p_this ) { audio_output_t * p_aout = (audio_output_t *)p_this; char * psz_name, * psz_format; const char * const * ppsz_compare = format_list; int i_channels, i = 0; psz_name = var_CreateGetString( p_this, "audiofile-file" ); if( !psz_name || !*psz_name ) { msg_Err( p_aout, "you need to specify an output file name" ); free( psz_name ); return VLC_EGENERIC; } /* Allocate structure */ p_aout->sys = malloc( sizeof( aout_sys_t ) ); if( p_aout->sys == NULL ) return VLC_ENOMEM; if( !strcmp( psz_name, "-" ) ) p_aout->sys->p_file = stdout; else p_aout->sys->p_file = vlc_fopen( psz_name, "wb" ); free( psz_name ); if ( p_aout->sys->p_file == NULL ) { free( p_aout->sys ); return VLC_EGENERIC; } p_aout->pf_play = Play; p_aout->pf_pause = NULL; p_aout->pf_flush = NULL; /* Audio format */ psz_format = var_CreateGetString( p_this, "audiofile-format" ); while ( *ppsz_compare != NULL ) { if ( !strncmp( *ppsz_compare, psz_format, strlen(*ppsz_compare) ) ) { break; } ppsz_compare++; i++; } if ( *ppsz_compare == NULL ) { msg_Err( p_aout, "cannot understand the format string (%s)", psz_format ); if( p_aout->sys->p_file != stdout ) fclose( p_aout->sys->p_file ); free( p_aout->sys ); free( psz_format ); return VLC_EGENERIC; } free( psz_format ); p_aout->format.i_format = format_int[i]; if ( AOUT_FMT_SPDIF( &p_aout->format ) ) { p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE; p_aout->format.i_frame_length = A52_FRAME_NB; } p_aout->volume_set = NULL; p_aout->mute_set = NULL; /* Channels number */ i_channels = var_CreateGetInteger( p_this, "audiofile-channels" ); if( i_channels > 0 && i_channels <= CHANNELS_MAX ) { p_aout->format.i_physical_channels = pi_channels_maps[i_channels]; } /* WAV header */ p_aout->sys->b_add_wav_header = var_CreateGetBool( p_this, "audiofile-wav" ); if( p_aout->sys->b_add_wav_header ) { /* Write wave header */ WAVEHEADER *wh = &p_aout->sys->waveh; memset( wh, 0, sizeof(*wh) ); switch( p_aout->format.i_format ) { case VLC_CODEC_FL32: wh->Format = WAVE_FORMAT_IEEE_FLOAT; wh->BitsPerSample = sizeof(float) * 8; break; case VLC_CODEC_U8: wh->Format = WAVE_FORMAT_PCM; wh->BitsPerSample = 8; break; case VLC_CODEC_S16L: default: wh->Format = WAVE_FORMAT_PCM; wh->BitsPerSample = 16; break; } wh->MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F'); wh->Length = 0; /* temp, to be filled in as we go */ wh->ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E'); wh->SubChunkID = VLC_FOURCC('f', 'm', 't', ' '); wh->SubChunkLength = 16; wh->Modus = aout_FormatNbChannels( &p_aout->format ); wh->SampleFreq = p_aout->format.i_rate; wh->BytesPerSample = wh->Modus * ( wh->BitsPerSample / 8 ); wh->BytesPerSec = wh->BytesPerSample * wh->SampleFreq; wh->DataChunkID = VLC_FOURCC('d', 'a', 't', 'a'); wh->DataLength = 0; /* temp, to be filled in as we go */ /* Header -> little endian format */ SetWLE( &wh->Format, wh->Format ); SetWLE( &wh->BitsPerSample, wh->BitsPerSample ); SetDWLE( &wh->SubChunkLength, wh->SubChunkLength ); SetWLE( &wh->Modus, wh->Modus ); SetDWLE( &wh->SampleFreq, wh->SampleFreq ); SetWLE( &wh->BytesPerSample, wh->BytesPerSample ); SetDWLE( &wh->BytesPerSec, wh->BytesPerSec ); if( fwrite( wh, sizeof(WAVEHEADER), 1, p_aout->sys->p_file ) != 1 ) { msg_Err( p_aout, "write error (%m)" ); } } return 0; }
/***************************************************************************** * Open: create a handle and open an alsa device ***************************************************************************** * This function opens an alsa device, through the alsa API. * * Note: the only heap-allocated string is psz_device. All the other pointers * are references to psz_device or to stack-allocated data. *****************************************************************************/ static int Open (vlc_object_t *obj) { audio_output_t * p_aout = (audio_output_t *)obj; /* Get device name */ char *psz_device; if (var_Type (p_aout, "audio-device")) psz_device = var_GetString (p_aout, "audio-device"); else psz_device = var_InheritString( p_aout, "alsa-audio-device" ); if (unlikely(psz_device == NULL)) return VLC_ENOMEM; snd_pcm_format_t pcm_format; /* ALSA sample format */ vlc_fourcc_t fourcc = p_aout->format.i_format; bool spdif = false; switch (fourcc) { case VLC_CODEC_F64B: pcm_format = SND_PCM_FORMAT_FLOAT64_BE; break; case VLC_CODEC_F64L: pcm_format = SND_PCM_FORMAT_FLOAT64_LE; break; case VLC_CODEC_F32B: pcm_format = SND_PCM_FORMAT_FLOAT_BE; break; case VLC_CODEC_F32L: pcm_format = SND_PCM_FORMAT_FLOAT_LE; break; case VLC_CODEC_FI32: fourcc = VLC_CODEC_FL32; pcm_format = SND_PCM_FORMAT_FLOAT; break; case VLC_CODEC_S32B: pcm_format = SND_PCM_FORMAT_S32_BE; break; case VLC_CODEC_S32L: pcm_format = SND_PCM_FORMAT_S32_LE; break; case VLC_CODEC_S24B: pcm_format = SND_PCM_FORMAT_S24_3BE; break; case VLC_CODEC_S24L: pcm_format = SND_PCM_FORMAT_S24_3LE; break; case VLC_CODEC_U24B: pcm_format = SND_PCM_FORMAT_U24_3BE; break; case VLC_CODEC_U24L: pcm_format = SND_PCM_FORMAT_U24_3LE; break; case VLC_CODEC_S16B: pcm_format = SND_PCM_FORMAT_S16_BE; break; case VLC_CODEC_S16L: pcm_format = SND_PCM_FORMAT_S16_LE; break; case VLC_CODEC_U16B: pcm_format = SND_PCM_FORMAT_U16_BE; break; case VLC_CODEC_U16L: pcm_format = SND_PCM_FORMAT_U16_LE; break; case VLC_CODEC_S8: pcm_format = SND_PCM_FORMAT_S8; break; case VLC_CODEC_U8: pcm_format = SND_PCM_FORMAT_U8; break; default: if (AOUT_FMT_SPDIF(&p_aout->format)) spdif = var_InheritBool (p_aout, "spdif"); if (HAVE_FPU) { fourcc = VLC_CODEC_FL32; pcm_format = SND_PCM_FORMAT_FLOAT; } else { fourcc = VLC_CODEC_S16N; pcm_format = SND_PCM_FORMAT_S16; } } /* Choose the IEC device for S/PDIF output: if the device is overridden by the user then it will be the one otherwise we compute the default device based on the output format. */ if (spdif && !strcmp (psz_device, DEFAULT_ALSA_DEVICE)) { unsigned aes3; switch (p_aout->format.i_rate) { #define FS(freq) \ case freq: aes3 = IEC958_AES3_CON_FS_ ## freq; break; FS( 44100) /* def. */ FS( 48000) FS( 32000) FS( 22050) FS( 24000) FS( 88200) FS(768000) FS( 96000) FS(176400) FS(192000) #undef FS default: aes3 = IEC958_AES3_CON_FS_NOTID; break; } free (psz_device); if (asprintf (&psz_device, "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x", IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO, IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER, 0, aes3) == -1) return VLC_ENOMEM; }