| /*************************************************************************** |
| * __________ __ ___. |
| * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| * \/ \/ \/ \/ \/ |
| * $Id$ |
| * |
| * Base declarations for working with software encoders |
| * |
| * Copyright (C) 2006 Michael Sevakis |
| * |
| * All files in this archive are subject to the GNU General Public License. |
| * See the file COPYING in the source tree root for full license agreement. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ****************************************************************************/ |
| |
| #ifndef ENC_BASE_H |
| #define ENC_BASE_H |
| |
| /** encoder config structures **/ |
| |
| /** aiff_enc.codec **/ |
| struct aiff_enc_config |
| { |
| #if 0 |
| unsigned long sample_depth; |
| #endif |
| }; |
| |
| /** mp3_enc.codec **/ |
| #define MP3_BITR_CAP_8 (1 << 0) |
| #define MP3_BITR_CAP_16 (1 << 1) |
| #define MP3_BITR_CAP_24 (1 << 2) |
| #define MP3_BITR_CAP_32 (1 << 3) |
| #define MP3_BITR_CAP_40 (1 << 4) |
| #define MP3_BITR_CAP_48 (1 << 5) |
| #define MP3_BITR_CAP_56 (1 << 6) |
| #define MP3_BITR_CAP_64 (1 << 7) |
| #define MP3_BITR_CAP_80 (1 << 8) |
| #define MP3_BITR_CAP_96 (1 << 9) |
| #define MP3_BITR_CAP_112 (1 << 10) |
| #define MP3_BITR_CAP_128 (1 << 11) |
| #define MP3_BITR_CAP_144 (1 << 12) |
| #define MP3_BITR_CAP_160 (1 << 13) |
| #define MP3_BITR_CAP_192 (1 << 14) |
| #define MP3_BITR_CAP_224 (1 << 15) |
| #define MP3_BITR_CAP_256 (1 << 16) |
| #define MP3_BITR_CAP_320 (1 << 17) |
| #define MP3_ENC_NUM_BITR 18 |
| |
| /* MPEG 1 */ |
| #define MPEG1_SAMPR_CAPS (SAMPR_CAP_32 | SAMPR_CAP_48 | SAMPR_CAP_44) |
| #define MPEG1_BITR_CAPS (MP3_BITR_CAP_32 | MP3_BITR_CAP_40 | MP3_BITR_CAP_48 | \ |
| MP3_BITR_CAP_56 | MP3_BITR_CAP_64 | MP3_BITR_CAP_80 | \ |
| MP3_BITR_CAP_96 | MP3_BITR_CAP_112 | MP3_BITR_CAP_128 | \ |
| MP3_BITR_CAP_160 | MP3_BITR_CAP_192 | MP3_BITR_CAP_224 | \ |
| MP3_BITR_CAP_256 | MP3_BITR_CAP_320) |
| |
| /* MPEG 2 */ |
| #define MPEG2_SAMPR_CAPS (SAMPR_CAP_22 | SAMPR_CAP_24 | SAMPR_CAP_16) |
| #define MPEG2_BITR_CAPS (MP3_BITR_CAP_8 | MP3_BITR_CAP_16 | MP3_BITR_CAP_24 | \ |
| MP3_BITR_CAP_32 | MP3_BITR_CAP_40 | MP3_BITR_CAP_48 | \ |
| MP3_BITR_CAP_56 | MP3_BITR_CAP_64 | MP3_BITR_CAP_80 | \ |
| MP3_BITR_CAP_96 | MP3_BITR_CAP_112 | MP3_BITR_CAP_128 | \ |
| MP3_BITR_CAP_144 | MP3_BITR_CAP_160) |
| |
| #if 0 |
| /* MPEG 2.5 */ |
| #define MPEG2_5_SAMPR_CAPS (SAMPR_CAP_8 | SAMPR_CAP_12 | SAMPR_CAP_11) |
| #define MPEG2_5_BITR_CAPS MPEG2_BITR_CAPS |
| #endif |
| |
| /* HAVE_MPEG* defines mainly apply to the bitrate menu */ |
| #if (REC_SAMPR_CAPS & MPEG1_SAMPR_CAPS) || defined (HAVE_SPDIF_REC) |
| #define HAVE_MPEG1_SAMPR |
| #endif |
| |
| #if (REC_SAMPR_CAPS & MPEG2_SAMPR_CAPS) || defined (HAVE_SPDIF_REC) |
| #define HAVE_MPEG2_SAMPR |
| #endif |
| |
| #if 0 |
| #if (REC_SAMPR_CAPS & MPEG2_5_SAMPR_CAPS) || defined (HAVE_SPDIF_REC) |
| #define HAVE_MPEG2_5_SAMPR |
| #endif |
| #endif /* 0 */ |
| |
| #define MP3_ENC_SAMPR_CAPS (MPEG1_SAMPR_CAPS | MPEG2_SAMPR_CAPS) |
| |
| /* This number is count of full encoder set */ |
| #define MP3_ENC_NUM_SAMPR 6 |
| |
| extern const unsigned long mp3_enc_sampr[MP3_ENC_NUM_SAMPR]; |
| extern const unsigned long mp3_enc_bitr[MP3_ENC_NUM_BITR]; |
| |
| struct mp3_enc_config |
| { |
| unsigned long bitrate; |
| }; |
| |
| #define MP3_ENC_BITRATE_CFG_DEFAULT 11 /* 128 */ |
| #define MP3_ENC_BITRATE_CFG_VALUE_LIST "8,16,24,32,40,48,56,64,80,96," \ |
| "112,128,144,160,192,224,256,320" |
| |
| /** wav_enc.codec **/ |
| #define WAV_ENC_SAMPR_CAPS SAMPR_CAP_ALL |
| |
| struct wav_enc_config |
| { |
| #if 0 |
| unsigned long sample_depth; |
| #endif |
| }; |
| |
| /** wavpack_enc.codec **/ |
| #define WAVPACK_ENC_SAMPR_CAPS SAMPR_CAP_ALL |
| |
| struct wavpack_enc_config |
| { |
| #if 0 |
| unsigned long sample_depth; |
| #endif |
| }; |
| |
| struct encoder_config |
| { |
| union |
| { |
| /* states which *_enc_config member is valid */ |
| int rec_format; /* REC_FORMAT_* value */ |
| int afmt; /* AFMT_* value */ |
| }; |
| |
| union |
| { |
| struct mp3_enc_config mp3_enc; |
| struct wavpack_enc_config wavpack_enc; |
| struct wav_enc_config wav_enc; |
| }; |
| }; |
| |
| /** Encoder chunk macros and definitions **/ |
| #define CHUNKF_START_FILE 0x0001ul /* This chunk starts a new file */ |
| #define CHUNKF_END_FILE 0x0002ul /* This chunk ends the current file */ |
| #define CHUNKF_PRERECORD 0x0010ul /* This chunk is prerecord data, |
| a new file could start anytime */ |
| #define CHUNKF_ABORT 0x0020ul /* Encoder should not finish this |
| chunk */ |
| #define CHUNKF_ERROR (~0ul ^ (~0ul >> 1)) /* An error has occured |
| (passed to/from encoder). Use the |
| sign bit to check (long)flags < 0. */ |
| #define CHUNKF_ALLFLAGS (0x0033ul | CHUNKF_ERROR) |
| |
| /* Header at the beginning of every encoder chunk */ |
| #ifdef PCMREC_PARANOID |
| #define ENC_CHUNK_MAGIC H_TO_BE32(('P' << 24) | ('T' << 16) | ('Y' << 8) | 'R') |
| #endif |
| struct enc_chunk_hdr |
| { |
| #ifdef PCMREC_PARANOID |
| unsigned long id; /* overflow detection - 'PTYR' - acronym for |
| "PTYR Tells You Right" ;) */ |
| #endif |
| unsigned long flags; /* in/out: flags used by encoder and file |
| writing */ |
| size_t enc_size; /* out: amount of encoder data written to |
| chunk */ |
| unsigned long num_pcm; /* out: number of PCM samples eaten during |
| processing |
| (<= size of allocated buffer) */ |
| unsigned char *enc_data; /* out: pointer to enc_size_written bytes |
| of encoded audio data in chunk */ |
| /* Encoder defined data follows header. Can be audio data + any other |
| stuff the encoder needs to handle on a per chunk basis */ |
| }; |
| |
| /* Paranoia: be sure header size is 4-byte aligned */ |
| #define ENC_CHUNK_HDR_SIZE \ |
| ALIGN_UP_P2(sizeof (struct enc_chunk_hdr), 2) |
| /* Skip the chunk header and return data */ |
| #define ENC_CHUNK_SKIP_HDR(t, hdr) \ |
| ((typeof (t))((char *)hdr + ENC_CHUNK_HDR_SIZE)) |
| /* Cast p to struct enc_chunk_hdr * */ |
| #define ENC_CHUNK_HDR(p) \ |
| ((struct enc_chunk_hdr *)(p)) |
| |
| enum enc_events |
| { |
| /* File writing events - data points to enc_file_event_data */ |
| ENC_START_FILE = 0, /* a new file has been opened and no data has yet |
| been written */ |
| ENC_WRITE_CHUNK, /* write the current chunk to disk */ |
| ENC_END_FILE, /* current file about to be closed and all valid |
| data has been written */ |
| /* Encoder buffer events - data points to enc_buffer_event_data */ |
| ENC_REC_NEW_STREAM, /* Take steps to finish current stream and start |
| new */ |
| }; |
| |
| /** |
| * encoder can write extra data to the file such as headers or more encoded |
| * samples and must update sizes and samples accordingly. |
| */ |
| struct enc_file_event_data |
| { |
| struct enc_chunk_hdr *chunk; /* Current chunk */ |
| size_t new_enc_size; /* New size of chunk */ |
| unsigned long new_num_pcm; /* New number of pcm in chunk */ |
| const char *filename; /* filename to open if ENC_START_FILE */ |
| int rec_file; /* Current file or < 0 if none */ |
| unsigned long num_pcm_samples; /* Current pcm sample count written to |
| file so far. */ |
| }; |
| |
| /** |
| * encoder may add some data to the end of the last and start of the next |
| * but must never yield when called so any encoding done should be absolutely |
| * minimal. |
| */ |
| struct enc_buffer_event_data |
| { |
| unsigned long flags; /* in: One or more of: |
| * CHUNKF_PRERECORD |
| * CHUNKF_END_FILE |
| * CHUNKF_START_FILE |
| */ |
| struct enc_chunk_hdr *pre_chunk; /* in: pointer to first prerecord |
| * chunk |
| */ |
| struct enc_chunk_hdr *chunk; /* in,out: chunk were split occurs - |
| * first chunk of start |
| */ |
| }; |
| |
| /** Callbacks called by encoder codec **/ |
| |
| /* parameters passed to encoder by enc_get_inputs */ |
| struct enc_inputs |
| { |
| unsigned long sample_rate; /* out - pcm frequency */ |
| int num_channels; /* out - number of audio channels */ |
| struct encoder_config *config; /* out - encoder settings */ |
| }; |
| |
| void enc_get_inputs(struct enc_inputs *inputs); |
| |
| /* parameters pass from encoder to enc_set_parameters */ |
| struct enc_parameters |
| { |
| /* IN parameters */ |
| int afmt; /* AFMT_* id - sanity checker */ |
| size_t chunk_size; /* max chunk size required */ |
| unsigned long enc_sample_rate; /* actual sample rate used by encoder |
| (for recorded time calculation) */ |
| size_t reserve_bytes; /* number of bytes to reserve immediately |
| following chunks */ |
| void (*events_callback)(enum enc_events event, |
| void *data); /* pointer to events callback */ |
| /* OUT parameters */ |
| unsigned char *enc_buffer; /* pointer to enc_buffer */ |
| size_t buf_chunk_size; /* size of chunks in enc_buffer */ |
| int num_chunks; /* number of chunks allotted to encoder */ |
| unsigned char *reserve_buffer; /* pointer to reserve_bytes bytes */ |
| }; |
| |
| /* set the encoder dimensions - called by encoder codec at initialization |
| and termination */ |
| void enc_set_parameters(struct enc_parameters *params); |
| /* returns pointer to next write chunk in circular buffer */ |
| struct enc_chunk_hdr * enc_get_chunk(void); |
| /* releases the current chunk into the available chunks */ |
| void enc_finish_chunk(void); |
| /* checks near empty state on pcm input buffer */ |
| int enc_pcm_buf_near_empty(void); |
| |
| #define PCM_MAX_FEED_SIZE 20000 /* max pcm size passed to encoder */ |
| |
| /* passes a pointer to next chunk of unprocessed wav data */ |
| unsigned char * enc_get_pcm_data(size_t size); |
| /* puts some pcm data back in the queue */ |
| size_t enc_unget_pcm_data(size_t size); |
| |
| #endif /* ENC_BASE_H */ |