Skip to content

Commit a84c3b4

Browse files
committed
Allow switch to change the sample rate after init.
1 parent c7231b6 commit a84c3b4

File tree

1 file changed

+32
-10
lines changed

1 file changed

+32
-10
lines changed

media.go

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,24 @@ func NopCloser[T any](w Writer[T]) WriteCloser[T] {
7171
}
7272

7373
func NewSwitchWriter(sampleRate int) *SwitchWriter {
74-
if sampleRate <= 0 {
75-
panic("invalid sample rate")
74+
// This protects from a case when sample rate is not initialized,
75+
// but still allows passing -1 to delay initialization.
76+
// If sample rate is still uninitialized when another writer is attached,
77+
// the SampleRate method will panic instead of this check.
78+
if sampleRate == 0 {
79+
panic("no sample rate specified")
7680
}
77-
return &SwitchWriter{
78-
sampleRate: sampleRate,
81+
if sampleRate < 0 {
82+
sampleRate = -1 // checked by SetSampleRate
7983
}
84+
w := &SwitchWriter{}
85+
w.sampleRate.Store(int32(sampleRate))
86+
return w
8087
}
8188

8289
type SwitchWriter struct {
83-
sampleRate int
8490
ptr atomic.Pointer[PCM16Writer]
91+
sampleRate atomic.Int32
8592
disabled atomic.Bool
8693
}
8794

@@ -108,8 +115,8 @@ func (s *SwitchWriter) Swap(w PCM16Writer) PCM16Writer {
108115
if w == nil {
109116
old = s.ptr.Swap(nil)
110117
} else {
111-
if w.SampleRate() != s.sampleRate {
112-
w = ResampleWriter(w, s.sampleRate)
118+
if rate := s.SampleRate(); rate != w.SampleRate() {
119+
w = ResampleWriter(w, rate)
113120
}
114121
old = s.ptr.Swap(&w)
115122
}
@@ -121,14 +128,29 @@ func (s *SwitchWriter) Swap(w PCM16Writer) PCM16Writer {
121128

122129
func (s *SwitchWriter) String() string {
123130
w := s.Get()
124-
return fmt.Sprintf("Switch(%d) -> %v", s.sampleRate, w)
131+
return fmt.Sprintf("Switch(%d) -> %v", s.sampleRate.Load(), w)
132+
}
133+
134+
// SetSampleRate sets a new sample rate for the switch. For this to work, NewSwitchWriter(-1) must be called.
135+
// The code will panic if sample rate is unset when a writer is attached, or if this method is called twice.
136+
func (s *SwitchWriter) SetSampleRate(rate int) {
137+
if rate <= 0 {
138+
panic("invalid sample rate")
139+
}
140+
if !s.sampleRate.CompareAndSwap(-1, int32(rate)) {
141+
panic("sample rate can only be changed once")
142+
}
125143
}
126144

145+
// SampleRate returns an expected sample rate for this writer. It panics if the sample rate is not specified.
127146
func (s *SwitchWriter) SampleRate() int {
128-
if s.sampleRate == 0 {
147+
rate := int(s.sampleRate.Load())
148+
if rate == 0 {
129149
panic("switch writer not initialized")
150+
} else if rate < 0 {
151+
panic("sample rate is unset on a switch writer")
130152
}
131-
return s.sampleRate
153+
return rate
132154
}
133155

134156
func (s *SwitchWriter) Close() error {

0 commit comments

Comments
 (0)