Ignore:
Timestamp:
Sep 10, 2008 7:48:45 PM (16 years ago)
Author:
nanang
Message:

Ticket #614: Added support for writing and reading WAV files encoded as 8 bit A-law/U-law.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/wav_player.c

    r2039 r2270  
    1818 */ 
    1919#include <pjmedia/wav_port.h> 
     20#include <pjmedia/alaw_ulaw.h> 
    2021#include <pjmedia/errno.h> 
    2122#include <pjmedia/wave.h> 
     
    3233 
    3334#define SIGNATURE           PJMEDIA_PORT_SIGNATURE('F', 'P', 'l', 'y') 
    34 #define BYTES_PER_SAMPLE    2 
    35  
     35#define BITS_PER_SAMPLE     16 
    3636 
    3737#if 1 
     
    5757    pjmedia_port     base; 
    5858    unsigned         options; 
     59    pjmedia_wave_fmt_tag fmt_tag; 
     60    pj_uint16_t      bytes_per_sample; 
    5961    pj_bool_t        eof; 
    6062    pj_size_t        bufsize; 
     
    146148 
    147149    /* Convert samples to host rep */ 
    148     samples_to_host((pj_int16_t*)fport->buf, fport->bufsize/BYTES_PER_SAMPLE); 
     150    samples_to_host((pj_int16_t*)fport->buf,  
     151                    fport->bufsize/fport->bytes_per_sample); 
    149152 
    150153    return PJ_SUCCESS; 
     
    166169    struct file_reader_port *fport; 
    167170    pj_off_t pos; 
    168     pj_status_t status; 
     171    pj_status_t status = PJ_SUCCESS; 
    169172 
    170173 
     
    236239    } 
    237240 
    238     /* Must be PCM with 16bits per sample */ 
    239     if (wave_hdr.fmt_hdr.fmt_tag != 1 || 
    240         wave_hdr.fmt_hdr.bits_per_sample != 16) 
    241     { 
    242         pj_file_close(fport->fd); 
    243         return PJMEDIA_EWAVEUNSUPP; 
    244     } 
    245  
    246     /* Block align must be 2*nchannels */ 
    247     if (wave_hdr.fmt_hdr.block_align != wave_hdr.fmt_hdr.nchan*BYTES_PER_SAMPLE) { 
    248         pj_file_close(fport->fd); 
    249         return PJMEDIA_EWAVEUNSUPP; 
    250     } 
     241    /* Validate format and its attributes (i.e: bits per sample, block align) */ 
     242    switch (wave_hdr.fmt_hdr.fmt_tag) { 
     243    case PJMEDIA_WAVE_FMT_TAG_PCM: 
     244        if (wave_hdr.fmt_hdr.bits_per_sample != 16 ||  
     245            wave_hdr.fmt_hdr.block_align != 2 * wave_hdr.fmt_hdr.nchan) 
     246            status = PJMEDIA_EWAVEUNSUPP; 
     247        break; 
     248 
     249    case PJMEDIA_WAVE_FMT_TAG_ALAW: 
     250    case PJMEDIA_WAVE_FMT_TAG_ULAW: 
     251        if (wave_hdr.fmt_hdr.bits_per_sample != 8 || 
     252            wave_hdr.fmt_hdr.block_align != wave_hdr.fmt_hdr.nchan) 
     253            status = PJMEDIA_ENOTVALIDWAVE; 
     254        break; 
     255 
     256    default: 
     257        status = PJMEDIA_EWAVEUNSUPP; 
     258        break; 
     259    } 
     260 
     261    if (status != PJ_SUCCESS) { 
     262        pj_file_close(fport->fd); 
     263        return status; 
     264    } 
     265 
     266    fport->fmt_tag = wave_hdr.fmt_hdr.fmt_tag; 
     267    fport->bytes_per_sample = wave_hdr.fmt_hdr.bits_per_sample / 8; 
    251268 
    252269    /* If length of fmt_header is greater than 16, skip the remaining 
     
    300317        return PJMEDIA_EWAVEUNSUPP; 
    301318    } 
    302     if (wave_hdr.data_hdr.len < 200) { 
     319    if (wave_hdr.data_hdr.len < ptime * wave_hdr.fmt_hdr.sample_rate * 
     320                                wave_hdr.fmt_hdr.nchan / 1000) 
     321    { 
    303322        pj_file_close(fport->fd); 
    304323        return PJMEDIA_EWAVETOOSHORT; 
     
    313332    fport->base.info.channel_count = wave_hdr.fmt_hdr.nchan; 
    314333    fport->base.info.clock_rate = wave_hdr.fmt_hdr.sample_rate; 
    315     fport->base.info.bits_per_sample = wave_hdr.fmt_hdr.bits_per_sample; 
     334    fport->base.info.bits_per_sample = BITS_PER_SAMPLE; 
    316335    fport->base.info.samples_per_frame = fport->base.info.clock_rate * 
    317336                                         wave_hdr.fmt_hdr.nchan * 
     
    338357     * doesn't handle this case). 
    339358     */ 
    340     if (fport->base.info.samples_per_frame * BYTES_PER_SAMPLE >= 
     359    if (fport->base.info.samples_per_frame * fport->bytes_per_sample >= 
    341360        fport->bufsize) 
    342361    { 
     
    524543    } 
    525544 
    526     //frame_size = fport->base.info.bytes_per_frame; 
    527     //pj_assert(frame->size == frame_size); 
    528     frame_size = frame->size; 
     545    //pj_assert(frame->size == fport->base.info.bytes_per_frame); 
     546    if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_PCM) { 
     547        frame_size = frame->size; 
     548        //frame->size = frame_size; 
     549    } else { 
     550        /* Must be ULAW or ALAW */ 
     551        pj_assert(fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ULAW ||  
     552                  fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ALAW); 
     553 
     554        frame_size = frame->size >> 1; 
     555        frame->size = frame_size << 1; 
     556    } 
    529557 
    530558    /* Copy frame from buffer. */ 
    531559    frame->type = PJMEDIA_FRAME_TYPE_AUDIO; 
    532     frame->size = frame_size; 
    533560    frame->timestamp.u64 = 0; 
    534561 
     
    580607    } 
    581608 
     609    if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ULAW || 
     610        fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ALAW) 
     611    { 
     612        unsigned i; 
     613        pj_uint16_t *dst; 
     614        pj_uint8_t *src; 
     615 
     616        dst = (pj_uint16_t*)frame->buf + frame_size - 1; 
     617        src = (pj_uint8_t*)frame->buf + frame_size - 1; 
     618 
     619        if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ULAW) { 
     620            for (i = 0; i < frame_size; ++i) { 
     621                *dst-- = (pj_uint16_t) pjmedia_ulaw2linear(*src--); 
     622            } 
     623        } else { 
     624            for (i = 0; i < frame_size; ++i) { 
     625                *dst-- = (pj_uint16_t) pjmedia_alaw2linear(*src--); 
     626            } 
     627        } 
     628    } 
     629 
    582630    return PJ_SUCCESS; 
    583631} 
Note: See TracChangeset for help on using the changeset viewer.