1 /*****************************************************************************
2 * voc.c : Creative Voice File (.VOC) demux module for vlc
3 *****************************************************************************
4 * Copyright (C) 2005 Rémi Denis-Courmont
6 * Authors: Rémi Denis-Courmont
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_demux.h>
37 /*****************************************************************************
39 *****************************************************************************/
40 static int Open ( vlc_object_t
* );
43 set_description( N_("VOC demuxer") )
44 set_category( CAT_INPUT
)
45 set_subcategory( SUBCAT_INPUT_DEMUX
)
46 set_capability( "demux", 10 )
48 add_file_extension("voc")
51 /*****************************************************************************
53 *****************************************************************************/
54 static int Demux ( demux_t
* );
55 static int Control( demux_t
*, int i_query
, va_list args
);
62 int64_t i_block_start
;
65 int64_t i_loop_offset
;
66 unsigned i_loop_count
;
67 unsigned i_silence_countdown
;
72 static const char ct_header
[] = "Creative Voice File\x1a";
74 /*****************************************************************************
75 * Open: check file and initializes structures
76 *****************************************************************************/
77 static int Open( vlc_object_t
* p_this
)
79 demux_t
*p_demux
= (demux_t
*)p_this
;
81 uint16_t i_data_offset
, i_version
;
83 if( vlc_stream_Peek( p_demux
->s
, &p_buf
, 26 ) < 26 )
86 if( memcmp( p_buf
, ct_header
, 20 ) )
90 i_data_offset
= GetWLE( p_buf
);
91 if ( i_data_offset
< 26 /* not enough room for full VOC header */ )
95 i_version
= GetWLE( p_buf
);
96 if( ( i_version
!= 0x10A ) && ( i_version
!= 0x114 ) )
97 return VLC_EGENERIC
; /* unknown VOC version */
100 if( GetWLE( p_buf
) != (uint16_t)(0x1234 + ~i_version
) )
103 /* We have a valid VOC header */
104 msg_Dbg( p_demux
, "CT Voice file v%d.%d", i_version
>> 8,
107 /* skip VOC header */
108 if( vlc_stream_Read( p_demux
->s
, NULL
, i_data_offset
) < i_data_offset
)
111 demux_sys_t
*p_sys
= vlc_obj_malloc( p_this
, sizeof (*p_sys
) );
112 if( unlikely(p_sys
== NULL
) )
115 p_sys
->i_silence_countdown
= p_sys
->i_block_start
= p_sys
->i_block_end
=
116 p_sys
->i_loop_count
= 0;
119 date_Init( &p_sys
->pts
, 1, 1 );
120 date_Set( &p_sys
->pts
, VLC_TICK_0
);
122 es_format_Init( &p_sys
->fmt
, AUDIO_ES
, 0 );
123 p_demux
->pf_demux
= Demux
;
124 p_demux
->pf_control
= Control
;
125 p_demux
->p_sys
= p_sys
;
130 static int fmtcmp( es_format_t
*ofmt
, es_format_t
*nfmt
)
132 return (ofmt
->audio
.i_bitspersample
!= nfmt
->audio
.i_bitspersample
)
133 || (ofmt
->audio
.i_rate
!= nfmt
->audio
.i_rate
)
134 || (ofmt
->audio
.i_channels
!= nfmt
->audio
.i_channels
);
139 * Converts old-style VOC sample rates to commonly used ones
140 * so as not to confuse sound card drivers.
141 * (I assume 16k, 24k and 32k are never found in .VOC files)
143 static unsigned int fix_voc_sr( unsigned int sr
)
161 static int ReadBlockHeader( demux_t
*p_demux
)
165 int32_t i_block_size
;
166 demux_sys_t
*p_sys
= p_demux
->p_sys
;
168 if( vlc_stream_Read( p_demux
->s
, buf
, 4 ) < 4 )
169 return VLC_EGENERIC
; /* EOF */
171 i_block_size
= GetDWLE( buf
) >> 8;
172 msg_Dbg( p_demux
, "new block: type: %u, size: %u",
173 (unsigned)*buf
, i_block_size
);
175 es_format_Init( &new_fmt
, AUDIO_ES
, 0 );
179 case 0: /* not possible : caught with earlier vlc_stream_Read */
183 if( i_block_size
< 2 )
187 if( vlc_stream_Read( p_demux
->s
, buf
, 2 ) < 2 )
190 switch( buf
[1] ) /* codec id */
193 new_fmt
.i_codec
= VLC_CODEC_U8
;
194 new_fmt
.audio
.i_bytes_per_frame
= 1;
195 new_fmt
.audio
.i_bitspersample
= 8;
198 new_fmt
.i_codec
= VLC_CODEC_ADPCM_SBPRO_4
;
199 new_fmt
.audio
.i_bytes_per_frame
= 1;
200 new_fmt
.audio
.i_bitspersample
= 4;
203 new_fmt
.i_codec
= VLC_CODEC_ADPCM_SBPRO_3
;
204 new_fmt
.audio
.i_bytes_per_frame
= 3;
205 new_fmt
.audio
.i_bitspersample
= 3;
208 new_fmt
.i_codec
= VLC_CODEC_ADPCM_SBPRO_2
;
209 new_fmt
.audio
.i_bytes_per_frame
= 1;
210 new_fmt
.audio
.i_bitspersample
= 2;
213 new_fmt
.i_codec
= VLC_CODEC_S16L
;
214 new_fmt
.audio
.i_bytes_per_frame
= 2;
215 new_fmt
.audio
.i_bitspersample
= 16;
218 new_fmt
.i_codec
= VLC_CODEC_ALAW
;
219 new_fmt
.audio
.i_bytes_per_frame
= 1;
220 new_fmt
.audio
.i_bitspersample
= 8;
223 new_fmt
.i_codec
= VLC_CODEC_MULAW
;
224 new_fmt
.audio
.i_bytes_per_frame
= 1;
225 new_fmt
.audio
.i_bitspersample
= 8;
228 msg_Err( p_demux
, "unsupported compression 0x%"PRIx8
, buf
[1] );
232 new_fmt
.audio
.i_channels
= 1;
233 new_fmt
.audio
.i_bytes_per_frame
*= new_fmt
.audio
.i_channels
;
234 new_fmt
.audio
.i_blockalign
= new_fmt
.audio
.i_bytes_per_frame
;
236 new_fmt
.audio
.i_frame_length
= new_fmt
.audio
.i_bytes_per_frame
* 8
237 / new_fmt
.audio
.i_bitspersample
;
239 new_fmt
.audio
.i_rate
= fix_voc_sr( 1000000L / (256L - buf
[0]) );
240 new_fmt
.i_bitrate
= new_fmt
.audio
.i_rate
* new_fmt
.audio
.i_bitspersample
241 * new_fmt
.audio
.i_channels
;
245 case 2: /* data block with same format as the previous one */
246 if( p_sys
->p_es
== NULL
)
247 goto corrupt
; /* no previous block! */
249 memcpy( &new_fmt
, &p_sys
->fmt
, sizeof( new_fmt
) );
252 case 3: /* silence block */
253 if( ( i_block_size
!= 3 )
254 || ( vlc_stream_Read( p_demux
->s
, buf
, 3 ) < 3 ) )
258 p_sys
->i_silence_countdown
= GetWLE( buf
);
260 new_fmt
.i_codec
= VLC_CODEC_U8
;
261 new_fmt
.audio
.i_rate
= fix_voc_sr( 1000000L / (256L - buf
[0]) );
262 new_fmt
.audio
.i_bytes_per_frame
= 1;
263 new_fmt
.audio
.i_frame_length
= 1;
264 new_fmt
.audio
.i_channels
= 1;
265 new_fmt
.audio
.i_blockalign
= 1;
266 new_fmt
.audio
.i_bitspersample
= 8;
267 new_fmt
.i_bitrate
= new_fmt
.audio
.i_rate
* 8;
270 case 6: /* repeat block */
271 if( ( i_block_size
!= 2 )
272 || ( vlc_stream_Read( p_demux
->s
, buf
, 2 ) < 2 ) )
276 p_sys
->i_loop_count
= GetWLE( buf
);
277 p_sys
->i_loop_offset
= vlc_stream_Tell( p_demux
->s
);
280 case 7: /* repeat end block */
281 if( i_block_size
!= 0 )
284 if( p_sys
->i_loop_count
> 0 )
286 if( vlc_stream_Seek( p_demux
->s
, p_sys
->i_loop_offset
) )
287 msg_Warn( p_demux
, "cannot loop: seek failed" );
289 p_sys
->i_loop_count
--;
295 * Block 8 is a big kludge to add stereo support to block 1 :
296 * A block of type 8 is always followed by a block of type 1
297 * and specifies the number of channels in that 1-block
298 * (normally block 1 are always mono). In practice, block type 9
299 * is used for stereo rather than 8
301 if( ( i_block_size
!= 4 )
302 || ( vlc_stream_Read( p_demux
->s
, buf
, 4 ) < 4 ) )
307 msg_Err( p_demux
, "unsupported compression" );
311 new_fmt
.i_codec
= VLC_CODEC_U8
;
314 new_fmt
.audio
.i_channels
= buf
[3] + 1; /* can't be nul */
315 new_fmt
.audio
.i_rate
= 256000000L /
316 ((65536L - GetWLE(buf
)) * new_fmt
.audio
.i_channels
);
317 new_fmt
.audio
.i_bytes_per_frame
= new_fmt
.audio
.i_channels
;
318 new_fmt
.audio
.i_frame_length
= 1;
319 new_fmt
.audio
.i_blockalign
= new_fmt
.audio
.i_bytes_per_frame
;
320 new_fmt
.audio
.i_bitspersample
= 8 * new_fmt
.audio
.i_bytes_per_frame
;
321 new_fmt
.i_bitrate
= new_fmt
.audio
.i_rate
* 8;
323 /* read subsequent block 1 */
324 if( vlc_stream_Read( p_demux
->s
, buf
, 4 ) < 4 )
325 return VLC_EGENERIC
; /* EOF */
327 i_block_size
= GetDWLE( buf
) >> 8;
328 msg_Dbg( p_demux
, "new block: type: %u, size: %u",
329 (unsigned)*buf
, i_block_size
);
330 if( i_block_size
< 2 )
334 if( vlc_stream_Read( p_demux
->s
, buf
, 2 ) < 2 )
339 msg_Err( p_demux
, "unsupported compression" );
345 case 9: /* newer data block with channel number and bits resolution */
346 if( i_block_size
< 12 )
350 if( ( vlc_stream_Read( p_demux
->s
, buf
, 8 ) < 8 )
351 || ( vlc_stream_Read( p_demux
->s
, NULL
, 4 ) < 4 ) )
354 new_fmt
.audio
.i_rate
= GetDWLE( buf
);
355 if( !new_fmt
.audio
.i_rate
)
357 new_fmt
.audio
.i_bitspersample
= buf
[4];
358 new_fmt
.audio
.i_channels
= buf
[5];
360 switch( GetWLE( &buf
[6] ) ) /* format */
362 case 0x0000: /* PCM */
363 switch( new_fmt
.audio
.i_bitspersample
)
366 new_fmt
.i_codec
= VLC_CODEC_U8
;
370 new_fmt
.i_codec
= VLC_CODEC_U16L
;
374 msg_Err( p_demux
, "unsupported bit res.: %u bits",
375 new_fmt
.audio
.i_bitspersample
);
380 case 0x0004: /* signed */
381 switch( new_fmt
.audio
.i_bitspersample
)
384 new_fmt
.i_codec
= VLC_CODEC_S8
;
388 new_fmt
.i_codec
= VLC_CODEC_S16L
;
392 msg_Err( p_demux
, "unsupported bit res.: %u bits",
393 new_fmt
.audio
.i_bitspersample
);
399 msg_Err( p_demux
, "unsupported compression" );
403 if( new_fmt
.audio
.i_channels
== 0 )
405 msg_Err( p_demux
, "0 channels detected" );
409 new_fmt
.audio
.i_bytes_per_frame
= new_fmt
.audio
.i_channels
410 * (new_fmt
.audio
.i_bitspersample
/ 8);
411 new_fmt
.audio
.i_frame_length
= 1;
412 new_fmt
.audio
.i_blockalign
= new_fmt
.audio
.i_bytes_per_frame
;
413 new_fmt
.i_bitrate
= 8 * new_fmt
.audio
.i_rate
414 * new_fmt
.audio
.i_bytes_per_frame
;
418 msg_Dbg( p_demux
, "unknown block type %u - skipping block",
421 case 4: /* blocks of non-audio types can be skipped */
423 if( vlc_stream_Read( p_demux
->s
, NULL
,
424 i_block_size
) < i_block_size
)
430 p_sys
->i_block_start
= vlc_stream_Tell( p_demux
->s
);
431 p_sys
->i_block_end
= p_sys
->i_block_start
+ i_block_size
;
433 if( i_block_size
|| p_sys
->i_silence_countdown
)
435 /* we've read a block with data in it - update decoder */
436 msg_Dbg( p_demux
, "fourcc: %4.4s, channels: %d, "
437 "freq: %d Hz, bitrate: %dKo/s, blockalign: %d, "
438 "bits/samples: %d", (char *)&new_fmt
.i_codec
,
439 new_fmt
.audio
.i_channels
, new_fmt
.audio
.i_rate
,
440 new_fmt
.i_bitrate
/ 8192, new_fmt
.audio
.i_blockalign
,
441 new_fmt
.audio
.i_bitspersample
);
443 if( ( p_sys
->p_es
!= NULL
) && fmtcmp( &p_sys
->fmt
, &new_fmt
) )
445 msg_Dbg( p_demux
, "codec change needed" );
446 es_out_Del( p_demux
->out
, p_sys
->p_es
);
450 if( p_sys
->p_es
== NULL
)
452 memcpy( &p_sys
->fmt
, &new_fmt
, sizeof( p_sys
->fmt
) );
453 date_Change( &p_sys
->pts
, p_sys
->fmt
.audio
.i_rate
, 1 );
454 p_sys
->p_es
= es_out_Add( p_demux
->out
, &p_sys
->fmt
);
455 if( unlikely(p_sys
->p_es
== NULL
) )
463 msg_Err( p_demux
, "corrupted file - halting demux" );
467 /*****************************************************************************
468 * Demux: read packet and send them to decoders
469 *****************************************************************************
470 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
471 *****************************************************************************/
472 #define MAX_READ_FRAME 1000
473 static int Demux( demux_t
*p_demux
)
475 demux_sys_t
*p_sys
= p_demux
->p_sys
;
477 int64_t i_read_frames
;
479 if( p_sys
->i_silence_countdown
== 0 )
481 int64_t i_offset
= vlc_stream_Tell( p_demux
->s
);
482 if( i_offset
>= p_sys
->i_block_end
)
484 if( ReadBlockHeader( p_demux
) != VLC_SUCCESS
)
485 return VLC_DEMUXER_EOF
;
486 return VLC_DEMUXER_SUCCESS
;
489 i_read_frames
= ( p_sys
->i_block_end
- i_offset
)
490 / p_sys
->fmt
.audio
.i_bytes_per_frame
;
492 if( i_read_frames
> MAX_READ_FRAME
)
493 i_read_frames
= MAX_READ_FRAME
;
495 p_block
= vlc_stream_Block( p_demux
->s
,
496 p_sys
->fmt
.audio
.i_bytes_per_frame
498 if( p_block
== NULL
)
500 msg_Warn( p_demux
, "cannot read data" );
501 return VLC_DEMUXER_EOF
;
505 { /* emulates silence from the stream */
506 i_read_frames
= p_sys
->i_silence_countdown
;
507 if( i_read_frames
> MAX_READ_FRAME
)
508 i_read_frames
= MAX_READ_FRAME
;
510 p_block
= block_Alloc( i_read_frames
);
511 if( p_block
== NULL
)
514 memset( p_block
->p_buffer
, 0, i_read_frames
);
515 p_sys
->i_silence_countdown
-= i_read_frames
;
518 p_block
->i_dts
= p_block
->i_pts
= VLC_TICK_0
+ date_Get( &p_sys
->pts
);
519 p_block
->i_nb_samples
= i_read_frames
* p_sys
->fmt
.audio
.i_frame_length
;
520 date_Increment( &p_sys
->pts
, p_block
->i_nb_samples
);
521 es_out_SetPCR( p_demux
->out
, p_block
->i_pts
);
522 assert(p_sys
->p_es
!= NULL
);
523 es_out_Send( p_demux
->out
, p_sys
->p_es
, p_block
);
525 return VLC_DEMUXER_SUCCESS
;
528 /*****************************************************************************
530 *****************************************************************************/
531 static int Control( demux_t
*p_demux
, int i_query
, va_list args
)
533 demux_sys_t
*p_sys
= p_demux
->p_sys
;
535 return demux_vaControlHelper( p_demux
->s
, p_sys
->i_block_start
,
537 p_sys
->fmt
.i_bitrate
,
538 p_sys
->fmt
.audio
.i_blockalign
,