📄 mpeg.c
字号:
if (id3->vbr) { if (id3->has_toc) { /* Use the TOC to find the new position */ unsigned int percent, remainder; int curtoc, nexttoc, plen; percent = (newtime*100)/id3->length; if (percent > 99) percent = 99; curtoc = id3->toc[percent]; if (percent < 99) nexttoc = id3->toc[percent+1]; else nexttoc = 256; newpos = (id3->filesize/256)*curtoc; /* Use the remainder to get a more accurate position */ remainder = (newtime*100)%id3->length; remainder = (remainder*100)/id3->length; plen = (nexttoc - curtoc)*(id3->filesize/256); newpos += (plen/100)*remainder; } else { /* No TOC exists, estimate the new position */ newpos = (id3->filesize / (id3->length / 1000)) * (newtime / 1000); } } else if (id3->bpf && id3->tpf) newpos = (newtime/id3->tpf)*id3->bpf; else { /* Not enough information to FF/Rewind */ id3->elapsed = oldtime; break; } if (newpos >= (int)(id3->filesize - id3->id3v1len)) { /* Don't seek right to the end of the file so that we can transition properly to the next song */ newpos = id3->filesize - id3->id3v1len - 1; } else if (newpos < (int)id3->first_frame_offset) { /* skip past id3v2 tag and other leading garbage */ newpos = id3->first_frame_offset; } if (mpeg_file >= 0) curpos = lseek(mpeg_file, 0, SEEK_CUR); else curpos = id3->filesize; if (num_tracks_in_memory() > 1) { /* We have started loading other tracks that need to be accounted for */ int i = tag_read_idx; int j = tag_write_idx - 1; if (j < 0) j = MAX_ID3_TAGS - 1; while (i != j) { curpos += id3tags[i]->id3.filesize; i = (i+1) & MAX_ID3_TAGS_MASK; } } diffpos = curpos - newpos; if(!filling && diffpos >= 0 && diffpos < mp3buflen) { int unplayed_space_left, unswapped_space_left; /* We are changing to a position that's already in memory, so we just move the DMA read pointer. */ mp3buf_read = mp3buf_write - diffpos; if (mp3buf_read < 0) { mp3buf_read += mp3buflen; } unplayed_space_left = get_unplayed_space(); unswapped_space_left = get_unswapped_space(); /* If unswapped_space_left is larger than unplayed_space_left, it means that the swapwrite pointer hasn't yet advanced up to the new location of the read pointer. We just move it, there is no need to swap data that won't be played anyway. */ if (unswapped_space_left > unplayed_space_left) { DEBUGF("Moved swapwrite\n"); mp3buf_swapwrite = mp3buf_read; play_pending = true; } if (mpeg_file>=0 && unplayed_space_left < low_watermark) { /* We need to load more data before starting */ filling = true; queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); play_pending = true; } else { /* resume will start at new position */ last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); mp3_play_data(mp3buf + mp3buf_read, last_dma_chunk_size, transfer_end); dma_underrun = false; } } else { /* Move to the new position in the file and start loading data */ reset_mp3_buffer(); if (num_tracks_in_memory() > 1) { /* We have to reload the current track */ close(mpeg_file); remove_all_non_current_tags(); mpeg_file = -1; } if (mpeg_file < 0) { mpeg_file = open(id3->path, O_RDONLY); if (mpeg_file < 0) { id3->elapsed = oldtime; break; } } if(-1 == lseek(mpeg_file, newpos, SEEK_SET)) { id3->elapsed = oldtime; break; } filling = true; queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); /* Tell the file loading code that we want to start playing as soon as we have some data */ play_pending = true; } id3->offset = newpos; break; } case MPEG_FLUSH_RELOAD: { int numtracks = num_tracks_in_memory(); bool reload_track = false; if (numtracks > 1) { /* Reload songs */ int next = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; /* Reset the buffer */ mp3buf_write = id3tags[next]->mempos; /* Reset swapwrite unless we're still swapping current track */ if (get_unplayed_space() <= get_playable_space()) mp3buf_swapwrite = mp3buf_write; close(mpeg_file); remove_all_non_current_tags(); mpeg_file = -1; reload_track = true; } else if (numtracks == 1 && mpeg_file < 0) { reload_track = true; } if(reload_track && new_file(1) >= 0) { /* Tell ourselves that we want more data */ queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); filling = true; } break; } case MPEG_NEED_DATA: free_space_left = mp3buf_read - mp3buf_write; /* We interpret 0 as "empty buffer" */ if(free_space_left <= 0) free_space_left = mp3buflen + free_space_left; unplayed_space_left = mp3buflen - free_space_left; /* Make sure that we don't fill the entire buffer */ free_space_left -= MPEG_HIGH_WATER; /* do we have any more buffer space to fill? */ if(free_space_left <= MPEG_HIGH_WATER) { DEBUGF("0\n"); filling = false; ata_sleep(); break; } /* Read small chunks while we are below the low water mark */ if(unplayed_space_left < low_watermark) amount_to_read = MIN(MPEG_LOW_WATER_CHUNKSIZE, free_space_left); else amount_to_read = free_space_left; /* Don't read more than until the end of the buffer */ amount_to_read = MIN(mp3buflen - mp3buf_write, amount_to_read);#if MEM == 8 amount_to_read = MIN(0x100000, amount_to_read);#endif /* #if MEM == 8 */ /* Read as much mpeg data as we can fit in the buffer */ if(mpeg_file >= 0) { DEBUGF("R\n"); t1 = current_tick; len = read(mpeg_file, mp3buf+mp3buf_write, amount_to_read); if(len > 0) { t2 = current_tick; DEBUGF("time: %d\n", t2 - t1); DEBUGF("R: %x\n", len); /* Now make sure that we don't feed the MAS with ID3V1 data */ if (len < amount_to_read) { int tagptr = mp3buf_write + len - 128; int i; char *tag = "TAG"; int taglen = 128; for(i = 0;i < 3;i++) { if(tagptr >= mp3buflen) tagptr -= mp3buflen; if(mp3buf[tagptr] != tag[i]) taglen = 0; tagptr++; } if(taglen) { /* Skip id3v1 tag */ DEBUGF("Skipping ID3v1 tag\n"); len -= taglen; /* The very rare case when the entire tag wasn't read in this read() call must be taken care of */ if(len < 0) len = 0; } } mp3buf_write += len; if(mp3buf_write >= mp3buflen) { mp3buf_write = 0; DEBUGF("W\n"); } /* Tell ourselves that we want more data */ queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); } else { if(len < 0) { DEBUGF("MPEG read error\n"); } close(mpeg_file); mpeg_file = -1; if(new_file(1) < 0) { /* No more data to play */ DEBUGF("No more files to play\n"); filling = false; } else { /* Tell ourselves that we want more data */ queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); } } } break; case MPEG_TRACK_CHANGE: track_change(); break;#ifndef USB_NONE case SYS_USB_CONNECTED: is_playing = false; paused = false; stop_playing();#ifndef SIMULATOR /* Tell the USB thread that we are safe */ DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n"); usb_acknowledge(SYS_USB_CONNECTED_ACK); /* Wait until the USB cable is extracted again */ usb_wait_for_disconnect(&mpeg_queue);#endif /* #ifndef SIMULATOR */ break;#endif /* #ifndef USB_NONE */ #ifdef HAVE_MAS3587F case MPEG_INIT_RECORDING: init_recording(); init_recording_done = true; break;#endif /* #ifdef HAVE_MAS3587F */ }#ifdef HAVE_MAS3587F } else { queue_wait(&mpeg_queue, &ev); switch(ev.id) { case MPEG_RECORD: if(is_prerecording) { int startpos, i; /* Go back prerecord_count seconds in the buffer */ startpos = prerecord_index - prerecord_count; if(startpos < 0) startpos += prerecording_max_seconds; /* Read the mp3 buffer pointer from the prerecord buffer */ startpos = prerecord_buffer[startpos]; DEBUGF("Start looking at address %x (%x)\n", mp3buf+startpos, startpos); saved_header = get_last_recorded_header(); mem_find_next_frame(startpos, &offset, 5000, saved_header); mp3buf_read = startpos + offset; DEBUGF("New mp3buf_read address: %x (%x)\n", mp3buf+mp3buf_read, mp3buf_read); /* Make room for headers */ mp3buf_read -= MPEG_RESERVED_HEADER_SPACE; if(mp3buf_read < 0) { /* Clear the bottom half */ memset(mp3buf, 0, mp3buf_read + MPEG_RESERVED_HEADER_SPACE); /* And the top half */ mp3buf_read += mp3buflen; memset(mp3buf + mp3buf_read, 0, mp3buflen - mp3buf_read); } else { memset(mp3buf + mp3buf_read, 0, MPEG_RESERVED_HEADER_SPACE); } /* Copy the empty ID3 header */ startpos = mp3buf_read; for(i = 0;i < (int)sizeof(empty_id3_header);i++) { mp3buf[startpos++] = empty_id3_header[i]; if(startpos == mp3buflen)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -