mirror of
				https://github.com/alsa-project/alsa-tools.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			166 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			166 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /***************************************************************************/
 | |
| /*  This code has been fully inspired from various place                   */
 | |
| /*  I will give their name later. May they be bless .... It works   	   */
 | |
| /*                                                                         */
 | |
| /*	For the moment test it.                                            */   
 | |
| /*									   */
 | |
| /* 27-08-00 -- Ze'ev Maor -- fixed recovery from flase syncword detection  */
 | |
| /* 								           */
 | |
| /* 24-08-00 -- Ze'ev Maor -- Modified for integrtion with DXR3-OMS-plugin  */  
 | |
| /***************************************************************************/
 | |
| 									   
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #include <unistd.h>
 | |
| #include <string.h>
 | |
| #include <inttypes.h>
 | |
| 
 | |
| #include <libac3/ac3.h>
 | |
| #include <libac3/ac3_internal.h>
 | |
| #include <libac3/parse.h>
 | |
| #include <libac3/crc.h>
 | |
| 
 | |
| #include "output.h"
 | |
| 
 | |
| void swab(const void*, void*, size_t);
 | |
| 
 | |
| #define BLOCK_SIZE 6144
 | |
| 
 | |
| static unsigned char buf[BLOCK_SIZE];
 | |
| static uint32_t sbuffer_size;
 | |
| static syncinfo_t syncinfo;
 | |
| static char *sbuffer;
 | |
| static int done_banner;
 | |
| 
 | |
| static uint32_t
 | |
| buffer_syncframe(syncinfo_t *syncinfo, uint8_t **start, uint8_t *end)
 | |
| {
 | |
|   uint8_t *cur = *start;
 | |
|   uint16_t syncword = syncinfo->syncword;
 | |
|   uint32_t ret = 0;
 | |
|  
 | |
|   //
 | |
|   // Find an ac3 sync frame.
 | |
|   //
 | |
|   while(syncword != 0x0b77)
 | |
|     {
 | |
|       if(cur >= end)
 | |
| 	goto done;
 | |
|       syncword = (syncword << 8) + *cur++;
 | |
|     }
 | |
|  
 | |
|   //need the next 3 bytes to decide how big the frame is
 | |
|   while(sbuffer_size < 3)
 | |
|     {
 | |
|       if(cur >= end)
 | |
| 	goto done;
 | |
|  
 | |
|       sbuffer[sbuffer_size++] = *cur++;
 | |
|     }
 | |
|                                                                                     
 | |
|   parse_syncinfo_data(syncinfo,sbuffer);
 | |
|  
 | |
|   while(sbuffer_size < (uint32_t)syncinfo->frame_size * 2 - 2)
 | |
|     {
 | |
|       if(cur >= end)
 | |
| 	goto done;
 | |
|  
 | |
|       sbuffer[sbuffer_size++] = *cur++;
 | |
|     }
 | |
|  
 | |
|   crc_init();
 | |
|   crc_process_frame(sbuffer,syncinfo->frame_size * 2 - 2);
 | |
| 	
 | |
|   if(!crc_validate())
 | |
|     {
 | |
|       //error_flag = 1;
 | |
|       fprintf(stderr,"** CRC failed - skipping frame **\n");
 | |
|       syncword = 0xffff;
 | |
|       sbuffer_size = 0;
 | |
|       bzero(buf,BLOCK_SIZE);
 | |
| 
 | |
|       goto done;
 | |
|     }                                                                           
 | |
|   //
 | |
|   //if we got to this point, we found a valid ac3 frame to decode
 | |
|   //
 | |
|  
 | |
|   //reset the syncword for next time
 | |
|   syncword = 0xffff;
 | |
|   sbuffer_size = 0;
 | |
|   ret = 1;
 | |
|  
 | |
|  done:
 | |
|   syncinfo->syncword = syncword;
 | |
|   *start = cur;
 | |
|   return ret;
 | |
| }                                                                                  
 | |
| 
 | |
| void
 | |
| init_spdif(void)
 | |
| {
 | |
|   sbuffer_size = 0;
 | |
|   sbuffer = &buf[10];
 | |
|   done_banner = 0;
 | |
| }
 | |
| 
 | |
| int
 | |
| output_spdif_zero(int frames)
 | |
| {
 | |
|   int res;
 | |
| 
 | |
|   buf[0] = 0x72; buf[1] = 0xf8;  // spdif syncword
 | |
|   buf[2] = 0x1f; buf[3] = 0x4e;  // ..............
 | |
|   buf[4] = 0x00;		 // null frame (no data) 
 | |
|   buf[5] = 7 << 5;		 // stream = 7
 | |
|   buf[6] = 0x00; buf[7] = 0x00;  // frame size
 | |
|   memset(&buf[8], 0, BLOCK_SIZE - 8);
 | |
|   while (frames-- > 0) {
 | |
|     res = output_play((short *)buf, BLOCK_SIZE / 2 / 2);	/* 2 channels, 16-bit samples */
 | |
|     if (res < 0)
 | |
|       return res;
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| int
 | |
| output_spdif_leadin(void)
 | |
| {
 | |
|   memset(buf, 0, 8);
 | |
|   return output_play((short *)buf, 8);
 | |
| }
 | |
| 
 | |
| int
 | |
| output_spdif(uint8_t *data_start, uint8_t *data_end, int quiet)
 | |
| {
 | |
|   int ret = 0, res;
 | |
|   
 | |
|   while(buffer_syncframe(&syncinfo, &data_start, data_end))
 | |
|     {
 | |
|       buf[0] = 0x72; buf[1] = 0xf8;	// spdif syncword
 | |
|       buf[2] = 0x1f; buf[3] = 0x4e;	// ..............
 | |
|       buf[4] = 0x01;			// AC3 data
 | |
|       buf[5] = buf[13] & 7;		// bsmod, stream = 0
 | |
|       buf[6] = (syncinfo.frame_size * 16) & 0xff;
 | |
|       buf[7] = ((syncinfo.frame_size * 16) >> 8) & 0xff;
 | |
|       buf[8] = 0x77; buf[9] = 0x0b;	// AC3 syncwork
 | |
|       
 | |
|       if (!done_banner && !quiet) {
 | |
|         fprintf(stdout,"AC3 Stream ");
 | |
| 	fprintf(stdout,"%2.1f KHz",syncinfo.sampling_rate * 1e-3);
 | |
|         fprintf(stdout,"%4d kbps",syncinfo.bit_rate);
 | |
|         fprintf(stdout,"\n");
 | |
|         done_banner = 1;
 | |
|       }
 | |
|       
 | |
| #ifndef _a_b_c_d_e_f /* WORDS_BIGENDIAN */
 | |
|       // extract_ac3 seems to write swabbed data
 | |
|       swab(&buf[10], &buf[10], syncinfo.frame_size * 2 - 2);
 | |
| #endif
 | |
|       res = output_play((short *)buf, BLOCK_SIZE / 2 / 2);	/* 2 channels, 16-bit samples */
 | |
|       ret = ret < 0 ? ret : res;
 | |
|       bzero(buf,BLOCK_SIZE);
 | |
|     }
 | |
|   return ret;
 | |
| }
 | 
