@@ -18,11 +18,9 @@ public sealed class ChatSegment : IDisposable
1818 public string ? AudioContentType { get ; private set ; }
1919 public float ? AudioLength { get ; private set ; }
2020
21- // 스트림 기반 음성 데이터 처리를 위한 새로운 프로퍼티
21+ // LOH 방지를 위한 ArrayPool 기반 메모리 관리
2222 internal IMemoryOwner < byte > ? AudioMemoryOwner { get ; private set ; }
2323 internal int AudioDataSize { get ; private set ; }
24-
25- // Dispose 멱등성 보장을 위한 플래그
2624 private bool _disposed ;
2725
2826
@@ -33,9 +31,6 @@ public sealed class ChatSegment : IDisposable
3331 public bool HasEmotion => ! string . IsNullOrEmpty ( Emotion ) ;
3432 public bool HasActions => Actions != null && Actions . Any ( ) ;
3533
36- /// <summary>
37- /// 메모리 효율적인 방식으로 음성 데이터에 접근합니다
38- /// </summary>
3934 public ReadOnlySpan < byte > GetAudioSpan ( )
4035 {
4136 if ( AudioMemoryOwner != null && AudioDataSize > 0 )
@@ -76,7 +71,6 @@ public static ChatSegment CreateAction(string action, int order = 0)
7671 return Create ( "" , null , new List < string > { action } , order ) ;
7772 }
7873
79- // Method to add audio data (returns new record instance)
8074 public ChatSegment WithAudioData ( byte [ ] audioData , string audioContentType , float audioLength )
8175 {
8276 return new ChatSegment
@@ -91,17 +85,7 @@ public ChatSegment WithAudioData(byte[] audioData, string audioContentType, floa
9185 } ;
9286 }
9387
94- /// <summary>
95- /// 메모리 효율적인 방식으로 음성 데이터를 추가합니다 (LOH 방지)
96- /// 소유권이 이전되므로 호출자는 더 이상 audioMemoryOwner를 해제하지 않아야 합니다.
97- /// </summary>
98- /// <param name="audioMemoryOwner">소유권이 이전될 메모리 소유자</param>
99- /// <param name="audioDataSize">실제 오디오 데이터 크기 (메모리 크기 이하여야 함)</param>
100- /// <param name="audioContentType">오디오 컨텐츠 타입</param>
101- /// <param name="audioLength">오디오 길이 (초)</param>
102- /// <returns>새로운 ChatSegment 인스턴스</returns>
103- /// <exception cref="ArgumentNullException">audioMemoryOwner가 null인 경우</exception>
104- /// <exception cref="ArgumentOutOfRangeException">audioDataSize가 유효하지 않은 경우</exception>
88+ // 소유권 이전: 호출자는 audioMemoryOwner를 해제하지 말 것
10589 public ChatSegment WithAudioMemory ( IMemoryOwner < byte > audioMemoryOwner , int audioDataSize , string audioContentType , float audioLength )
10690 {
10791 if ( audioMemoryOwner is null )
@@ -113,7 +97,7 @@ public ChatSegment WithAudioMemory(IMemoryOwner<byte> audioMemoryOwner, int audi
11397 audioDataSize ,
11498 $ "audioDataSize는 0 이상 { audioMemoryOwner . Memory . Length } 이하여야 합니다.") ;
11599
116- // 기존 AudioMemoryOwner가 있다면 해제 (소유권 이전)
100+ // 기존 소유자 해제
117101 this . AudioMemoryOwner ? . Dispose ( ) ;
118102
119103 return new ChatSegment
@@ -126,14 +110,11 @@ public ChatSegment WithAudioMemory(IMemoryOwner<byte> audioMemoryOwner, int audi
126110 AudioDataSize = audioDataSize ,
127111 AudioContentType = audioContentType ,
128112 AudioLength = audioLength ,
129- // 기존 AudioData는 null로 설정하여 중복 저장 방지
130113 AudioData = null
131114 } ;
132115 }
133116
134- /// <summary>
135- /// 음성 데이터를 배열로 변환합니다 (필요한 경우에만 사용)
136- /// </summary>
117+ // 필요시만 사용 - LOH 위험 있음
137118 public byte [ ] ? GetAudioDataAsArray ( )
138119 {
139120 if ( AudioData != null )
@@ -150,19 +131,11 @@ public ChatSegment WithAudioMemory(IMemoryOwner<byte> audioMemoryOwner, int audi
150131 return null ;
151132 }
152133
153- /// <summary>
154- /// 리소스 해제 (IMemoryOwner 해제)
155- /// 멱등성을 보장하여 여러 번 호출해도 안전합니다.
156- /// </summary>
157134 public void Dispose ( )
158135 {
159136 if ( _disposed ) return ;
160-
161- // 관리형 리소스만 해제 (IMemoryOwner)
162137 AudioMemoryOwner ? . Dispose ( ) ;
163-
164138 _disposed = true ;
165- // 파이널라이저가 없으므로 GC.SuppressFinalize 불필요
166139 }
167140 }
168141}
0 commit comments