瀏覽代碼

CUEParser: add sector_length

Petteri Aimonen 2 年之前
父節點
當前提交
562ef302ed
共有 4 個文件被更改,包括 81 次插入3 次删除
  1. 44 1
      lib/CUEParser/src/CUEParser.cpp
  2. 18 0
      lib/CUEParser/src/CUEParser.h
  3. 12 2
      lib/CUEParser/test/CUEParser_test.cpp
  4. 7 0
      lib/CUEParser/test/Makefile

+ 44 - 1
lib/CUEParser/src/CUEParser.cpp

@@ -56,14 +56,22 @@ void CUEParser::restart()
 
 const CUETrackInfo *CUEParser::next_track()
 {
+    // Previous track info is needed to track file offset
+    uint32_t prev_data_start = m_track_info.data_start;
+    uint32_t prev_sector_length = get_sector_length(m_track_info.file_mode, m_track_info.track_mode); // Defaults to 2352 before first track
+
     bool got_track = false;
     bool got_data = false;
-    while(start_line() && !(got_track && got_data))
+    while(!(got_track && got_data) && start_line())
     {
         if (strncasecmp(m_parse_pos, "FILE ", 5) == 0)
         {
             const char *p = read_quoted(m_parse_pos + 5, m_track_info.filename, sizeof(m_track_info.filename));
             m_track_info.file_mode = parse_file_mode(skip_space(p));
+            m_track_info.file_offset = 0;
+            m_track_info.track_mode = CUETrack_AUDIO;
+            prev_data_start = 0;
+            prev_sector_length = get_sector_length(m_track_info.file_mode, m_track_info.track_mode);
         }
         else if (strncasecmp(m_parse_pos, "TRACK ", 6) == 0)
         {
@@ -71,9 +79,11 @@ const CUETrackInfo *CUEParser::next_track()
             char *endptr;
             m_track_info.track_number = strtoul(track_num, &endptr, 10);
             m_track_info.track_mode = parse_track_mode(skip_space(endptr));
+            m_track_info.sector_length = get_sector_length(m_track_info.file_mode, m_track_info.track_mode);
             m_track_info.pregap_start = 0;
             m_track_info.unstored_pregap_length = 0;
             m_track_info.data_start = 0;
+            m_track_info.track_start = 0;
             got_track = true;
             got_data = false;
         }
@@ -81,6 +91,7 @@ const CUETrackInfo *CUEParser::next_track()
         {
             const char *time_str = skip_space(m_parse_pos + 7);
             m_track_info.unstored_pregap_length = parse_time(time_str);
+            m_track_info.pregap_start = 0;
         }
         else if (strncasecmp(m_parse_pos, "INDEX ", 6) == 0)
         {
@@ -94,9 +105,11 @@ const CUETrackInfo *CUEParser::next_track()
             if (index == 0)
             {
                 m_track_info.pregap_start = time;
+                m_track_info.track_start = time;
             }
             else if (index == 1)
             {
+                m_track_info.file_offset += (uint64_t)(time - prev_data_start) * prev_sector_length;
                 m_track_info.data_start = time;
                 got_data = true;
             }
@@ -105,6 +118,11 @@ const CUETrackInfo *CUEParser::next_track()
         next_line();
     }
 
+    if (got_data && m_track_info.track_start == 0)
+    {
+        m_track_info.track_start = m_track_info.data_start;
+    }
+
     if (got_track && got_data)
         return &m_track_info;
     else
@@ -232,4 +250,29 @@ CUETrackMode CUEParser::parse_track_mode(const char *src)
         return CUETrack_CDI_2352;
     else
         return CUETrack_MODE1_2048; // Default to data track
+}
+
+uint32_t CUEParser::get_sector_length(CUEFileMode filemode, CUETrackMode trackmode)
+{
+    if (filemode == CUEFile_BINARY || filemode == CUEFile_MOTOROLA)
+    {
+        switch (trackmode)
+        {
+            case CUETrack_AUDIO:        return 2352;
+            case CUETrack_CDG:          return 2448;
+            case CUETrack_MODE1_2048:   return 2048;
+            case CUETrack_MODE1_2352:   return 2352;
+            case CUETrack_MODE2_2048:   return 2048;
+            case CUETrack_MODE2_2324:   return 2324;
+            case CUETrack_MODE2_2336:   return 2336;
+            case CUETrack_MODE2_2352:   return 2352;
+            case CUETrack_CDI_2336:     return 2336;
+            case CUETrack_CDI_2352:     return 2352;
+            default:                    return 2048;
+        }
+    }
+    else
+    {
+        return 0;
+    }
 }

+ 18 - 0
lib/CUEParser/src/CUEParser.h

@@ -50,14 +50,29 @@ enum CUETrackMode
 
 struct CUETrackInfo
 {
+    // Source file name and file type, and offset to start of track data in bytes.
     char filename[CUE_MAX_FILENAME+1];
     CUEFileMode file_mode;
+    uint64_t file_offset;
+
+    // Track number and mode in CD format
     int track_number;
     CUETrackMode track_mode;
 
+    // Sector length for this track in bytes in the file, or 0 for audio files
+    uint32_t sector_length;
+
+    // Unstored pregap length, in CD frames, or 0
     uint32_t unstored_pregap_length;
+
+    // LBA start position of the pregap of this track (in CD frames)
     uint32_t pregap_start;
+
+    // LBA start position of the data area of this track (in CD frames)
     uint32_t data_start;
+
+    // Track start, either pregap_start or if no pregap, data_start.
+    uint32_t track_start;
 };
 
 class CUEParser
@@ -105,4 +120,7 @@ protected:
 
     // Parse track mode into enum
     CUETrackMode parse_track_mode(const char *src);
+
+    // Get sector length in file from track mode
+    uint32_t get_sector_length(CUEFileMode filemode, CUETrackMode trackmode);
 };

+ 12 - 2
lib/CUEParser/test/CUEParser_test.cpp

@@ -40,8 +40,10 @@ FILE "Sound.wav" WAVE
     {
         TEST(strcmp(track->filename, "Image Name.bin") == 0);
         TEST(track->file_mode == CUEFile_BINARY);
+        TEST(track->file_offset == 0);
         TEST(track->track_number == 1);
         TEST(track->track_mode == CUETrack_MODE1_2048);
+        TEST(track->sector_length == 2048);
         TEST(track->unstored_pregap_length == 0);
         TEST(track->data_start == 0);
     }
@@ -49,27 +51,33 @@ FILE "Sound.wav" WAVE
     COMMENT("Test TRACK 02 (audio with pregap)");
     track = parser.next_track();
     TEST(track != NULL);
+    uint32_t start2 = ((2 * 60) + 47) * 75 + 20;
     if (track)
     {
         TEST(strcmp(track->filename, "Image Name.bin") == 0);
         TEST(track->file_mode == CUEFile_BINARY);
+        TEST(track->file_offset == 2048 * start2);
         TEST(track->track_number == 2);
         TEST(track->track_mode == CUETrack_AUDIO);
+        TEST(track->sector_length == 2352);
         TEST(track->unstored_pregap_length == 2 * 75);
-        TEST(track->data_start == ((2 * 60) + 47) * 75 + 20);
+        TEST(track->data_start == start2);
     }
 
     COMMENT("Test TRACK 03 (audio with index 0)");
     track = parser.next_track();
     TEST(track != NULL);
+    uint32_t start3 = ((7 * 60) + 55) * 75 + 65;
     if (track)
     {
         TEST(strcmp(track->filename, "Image Name.bin") == 0);
         TEST(track->file_mode == CUEFile_BINARY);
+        TEST(track->file_offset == 2048 * start2 + 2352 * (start3 - start2));
         TEST(track->track_number == 3);
         TEST(track->track_mode == CUETrack_AUDIO);
+        TEST(track->sector_length == 2352);
         TEST(track->pregap_start == ((7 * 60) + 55) * 75 + 58);
-        TEST(track->data_start == ((7 * 60) + 55) * 75 + 65);
+        TEST(track->data_start == start3);
     }
 
     COMMENT("Test TRACK 11 (audio from wav)");
@@ -79,8 +87,10 @@ FILE "Sound.wav" WAVE
     {
         TEST(strcmp(track->filename, "Sound.wav") == 0);
         TEST(track->file_mode == CUEFile_WAVE);
+        TEST(track->file_offset == 0);
         TEST(track->track_number == 11);
         TEST(track->track_mode == CUETrack_AUDIO);
+        TEST(track->sector_length == 0);
         TEST(track->pregap_start == 0);
         TEST(track->data_start == 2 * 75);
     }

+ 7 - 0
lib/CUEParser/test/Makefile

@@ -0,0 +1,7 @@
+# Run basic unit tests for the CUEParser library
+
+all: CUEParser_test
+	./CUEParser_test
+
+CUEParser_test: CUEParser_test.cpp ../src/CUEParser.cpp
+	g++ -Wall -Wextra -o $@ -I ../src $^