⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg.c

📁 编译后直接运行的MP3播放器全部C语言源代码 一个包含FAT文件系统、系统引导 Boot、FLASH Driver等内容的
💻 C
📖 第 1 页 / 共 5 页
字号:
        space += mp3buflen;    return space;}static int get_unplayed_space_current_song(void){    int space;    if (num_tracks_in_memory() > 1)    {        int track_offset = (tag_read_idx+1) & MAX_ID3_TAGS_MASK;        space = id3tags[track_offset]->mempos - mp3buf_read;    }    else    {        space = mp3buf_write - mp3buf_read;    }    if (space < 0)        space += mp3buflen;    return space;}static int get_unswapped_space(void){    int space = mp3buf_write - mp3buf_swapwrite;    if (space < 0)        space += mp3buflen;    return space;}#ifdef HAVE_MAS3587Fstatic int get_unsaved_space(void){    int space = mp3buf_write - mp3buf_read;    if (space < 0)        space += mp3buflen;    return space;}#endif /* #ifdef HAVE_MAS3587F */#ifdef HAVE_MAS3587F#ifdef DEBUGstatic long timing_info_index = 0;static long timing_info[1024];#endif /* #ifdef DEBUG */static bool inverted_pr;static unsigned long num_rec_bytes;static unsigned long num_recorded_frames;static void drain_dma_buffer(void){    if(inverted_pr)    {        while((*((volatile unsigned char *)PBDR_ADDR) & 0x40))        {            or_b(0x08, &PADRH);                        while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);                                /* It must take at least 5 cycles before               the data is read */            asm(" nop\n nop\n nop\n");            asm(" nop\n nop\n nop\n");            and_b(~0x08, &PADRH);            while(!(*((volatile unsigned char *)PBDR_ADDR) & 0x80));        }    }    else    {        while((*((volatile unsigned char *)PBDR_ADDR) & 0x40))        {            and_b(~0x08, &PADRH);                        while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);                        /* It must take at least 5 cycles before               the data is read */            asm(" nop\n nop\n nop\n");            asm(" nop\n nop\n nop\n");                                or_b(0x08, &PADRH);            while(!(*((volatile unsigned char *)PBDR_ADDR) & 0x80));        }    }}#endif /* #ifdef HAVE_MAS3587F */void rec_tick (void) __attribute__ ((section (".icode")));void rec_tick(void){#ifdef HAVE_MAS3587F    int i;    int num_bytes;    if(is_recording && (PBDR & 0x4000))    {#ifdef DEBUG        timing_info[timing_info_index++] = current_tick;        TCNT2 = 0;#endif /* #ifdef DEBUG */        /* We read as long as EOD is high, but max 30 bytes.           This code is optimized, and should probably be           written in assembler instead. */        if(inverted_pr)        {            i = 0;            while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)                  && i < 30)            {                or_b(0x08, &PADRH);                while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);                                /* It must take at least 5 cycles before                   the data is read */                asm(" nop\n nop\n nop\n");                mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;                                if(mp3buf_write >= mp3buflen)                    mp3buf_write = 0;                i++;                                and_b(~0x08, &PADRH);                /* No wait for /RTW, cause it's not necessary */            }        }        else /* !inverted_pr */        {            i = 0;            while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)                  && i < 30)            {                and_b(~0x08, &PADRH);                                while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);                                /* It must take at least 5 cycles before                   the data is read */                asm(" nop\n nop\n nop\n");                mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;                                if(mp3buf_write >= mp3buflen)                    mp3buf_write = 0;                i++;                                or_b(0x08, &PADRH);                /* No wait for /RTW, cause it's not necessary */            }        }#ifdef DEBUG        timing_info[timing_info_index++] = TCNT2 + (i << 16);        timing_info_index &= 0x3ff;#endif /* #ifdef DEBUG */        num_rec_bytes += i;                if(is_prerecording)        {            if(TIME_AFTER(current_tick, prerecord_timeout))            {                prerecord_timeout = current_tick + HZ;                /* Store the write pointer every second */                prerecord_buffer[prerecord_index++] = mp3buf_write;                /* Wrap if necessary */                if(prerecord_index == prerecording_max_seconds)                    prerecord_index = 0;                /* Update the number of seconds recorded */                if(prerecord_count < prerecording_max_seconds)                    prerecord_count++;            }        }        else        {            /* Signal to save the data if we are running out of buffer               space */            num_bytes = mp3buf_write - mp3buf_read;            if(num_bytes < 0)                num_bytes += mp3buflen;                        if(mp3buflen - num_bytes < MPEG_RECORDING_LOW_WATER && !saving)            {                saving = true;                queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);                wake_up_thread();            }        }    }#endif /* #ifdef HAVE_MAS3587F */}void playback_tick(void){    id3tags[tag_read_idx]->id3.elapsed +=        (current_tick - last_dma_tick) * 1000 / HZ;    last_dma_tick = current_tick;}static void reset_mp3_buffer(void){    mp3buf_read = 0;    mp3buf_write = 0;    mp3buf_swapwrite = 0;    lowest_watermark_level = mp3buflen;} /* DMA transfer end interrupt callback */static void transfer_end(unsigned char** ppbuf, int* psize){    if(playing && !paused)    {        int unplayed_space_left;        int space_until_end_of_buffer;        int track_offset = (tag_read_idx+1) & MAX_ID3_TAGS_MASK;        mp3buf_read += last_dma_chunk_size;        if(mp3buf_read >= mp3buflen)            mp3buf_read = 0;            /* First, check if we are on a track boundary */        if (num_tracks_in_memory() > 0)        {            if (mp3buf_read == id3tags[track_offset]->mempos)            {                queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0);                track_offset = (track_offset+1) & MAX_ID3_TAGS_MASK;            }        }                unplayed_space_left = get_unplayed_space();                space_until_end_of_buffer = mp3buflen - mp3buf_read;                if(!filling && unplayed_space_left < low_watermark)        {            filling = true;            queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);        }                if(unplayed_space_left)        {            last_dma_chunk_size = MIN(0x2000, unplayed_space_left);            last_dma_chunk_size = MIN(last_dma_chunk_size,                                      space_until_end_of_buffer);            /* several tracks loaded? */            if (num_tracks_in_memory() > 1)            {                /* will we move across the track boundary? */                if (( mp3buf_read < id3tags[track_offset]->mempos ) &&                    ((mp3buf_read+last_dma_chunk_size) >                     id3tags[track_offset]->mempos ))                {                    /* Make sure that we end exactly on the boundary */                    last_dma_chunk_size = id3tags[track_offset]->mempos                        - mp3buf_read;                }            }            *psize = last_dma_chunk_size & 0xffff;            *ppbuf = mp3buf + mp3buf_read;            id3tags[tag_read_idx]->id3.offset += last_dma_chunk_size;            /* Update the watermark debug level */            if(unplayed_space_left < lowest_watermark_level)                lowest_watermark_level = unplayed_space_left;        }        else        {            /* Check if the end of data is because of a hard disk error.               If there is an open file handle, we are still playing music.               If not, the last file has been loaded, and the file handle is               closed. */            if(mpeg_file >= 0)            {                /* Update the watermark debug level */                if(unplayed_space_left < lowest_watermark_level)                    lowest_watermark_level = unplayed_space_left;                                DEBUGF("DMA underrun.\n");                dma_underrun = true;            }            else            {                DEBUGF("No more MP3 data. Stopping.\n");                queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0);                playing = false;                is_playing = false;            }            *psize = 0; /* no more transfer */        }    }    wake_up_thread();}static int add_track_to_tag_list(char *filename){    struct id3tag *t = NULL;    int i;    /* find a free tag */    for (i=0; i < MAX_ID3_TAGS_MASK; i++ )        if ( !_id3tags[i].used )            t = &_id3tags[i];    if(t)    {        /* grab id3 tag of new file and           remember where in memory it starts */        if(mp3info(&(t->id3), filename))        {            DEBUGF("Bad mp3\n");            return -1;        }        t->mempos = mp3buf_write;        t->id3.elapsed = 0;        if(!append_tag(t))        {            DEBUGF("Tag list is full\n");        }        else            t->used = true;    }    else    {        DEBUGF("No memory available for id3 tag");    }    return 0;}/* If next_track is true, opens the next track, if false, opens prev track */static int new_file(int steps){    int max_steps = playlist_amount();    int start = num_tracks_in_memory() - 1;    if (start < 0)        start = 0;    do {        char *trackname;        trackname = playlist_peek( start + steps );        if ( !trackname )            return -1;                DEBUGF("playing %s\n", trackname);                mpeg_file = open(trackname, O_RDONLY);        if(mpeg_file < 0) {            DEBUGF("Couldn't open file: %s\n",trackname);            steps++;            /* Bail out if no file could be opened */            if(steps > max_steps)                return -1;        }        else        {            int new_tag_idx = tag_write_idx;            if(add_track_to_tag_list(trackname))            {                /* Bad mp3 file */                steps++;                close(mpeg_file);                mpeg_file = -1;            }            else            {                /* skip past id3v2 tag */                lseek(mpeg_file,                       id3tags[new_tag_idx]->id3.first_frame_offset,                      SEEK_SET);                id3tags[new_tag_idx]->id3.index = steps;                id3tags[new_tag_idx]->id3.offset = 0;                if(id3tags[new_tag_idx]->id3.vbr)                    /* Average bitrate * 1.5 */                    recalculate_watermark(                        (id3tags[new_tag_idx]->id3.bitrate * 3) / 2);                else                    recalculate_watermark(                        id3tags[new_tag_idx]->id3.bitrate);                                }        }    } while ( mpeg_file < 0 );    return 0;}static void stop_playing(void){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -