@@ -14,6 +14,8 @@ export function SoundsTab() {
1414 const sounds = useStore ( soundMap ) ;
1515 const { soundsFilter } = useSettings ( ) ;
1616 const [ search , setSearch ] = useState ( '' ) ;
17+ const { BASE_URL } = import . meta. env ;
18+ const baseNoTrailing = BASE_URL . endsWith ( '/' ) ? BASE_URL . slice ( 0 , - 1 ) : BASE_URL ;
1719
1820 const soundEntries = useMemo ( ( ) => {
1921 if ( ! sounds ) {
@@ -37,6 +39,9 @@ export function SoundsTab() {
3739 if ( soundsFilter === 'synths' ) {
3840 return filtered . filter ( ( [ _ , { data } ] ) => [ 'synth' , 'soundfont' ] . includes ( data . type ) ) ;
3941 }
42+ if ( soundsFilter === 'importSounds' ) {
43+ return [ ] ;
44+ }
4045 return filtered ;
4146 } , [ sounds , soundsFilter , search ] ) ;
4247
@@ -51,7 +56,6 @@ export function SoundsTab() {
5156 ref ?. stop ( getAudioContext ( ) . currentTime + 0.01 ) ;
5257 } ) ;
5358 } ) ;
54-
5559 return (
5660 < div id = "sounds-tab" className = "px-4 flex flex-col w-full h-full text-foreground" >
5761 < Textbox placeholder = "Search" value = { search } onChange = { ( v ) => setSearch ( v ) } />
@@ -65,9 +69,9 @@ export function SoundsTab() {
6569 drums : 'drum-machines' ,
6670 synths : 'Synths' ,
6771 user : 'User' ,
72+ importSounds : 'import-sounds' ,
6873 } }
6974 > </ ButtonGroup >
70- < ImportSoundsButton onComplete = { ( ) => settingsMap . setKey ( 'soundsFilter' , 'user' ) } />
7175 </ div >
7276
7377 < div className = "min-h-0 max-h-full grow overflow-auto text-sm break-normal pb-2" >
@@ -101,7 +105,55 @@ export function SoundsTab() {
101105 </ span >
102106 ) ;
103107 } ) }
104- { ! soundEntries . length ? 'No custom sounds loaded in this pattern (yet).' : '' }
108+ { ! soundEntries . length && soundsFilter === 'importSounds' ? (
109+ < div className = "prose dark:prose-invert min-w-full pt-2 pb-8 px-4" >
110+ < ImportSoundsButton onComplete = { ( ) => settingsMap . setKey ( 'soundsFilter' , 'user' ) } />
111+ < p >
112+ To import sounds into strudel, they must be contained{ ' ' }
113+ < a href = { `${ baseNoTrailing } /learn/samples/#from-disk-via-import-sounds` } target = "_blank" >
114+ within a folder or subfolder
115+ </ a >
116+ . The best way to do this is to upload a “samples” folder containing subfolders of individual sounds or
117+ soundbanks (see diagram below).{ ' ' }
118+ </ p >
119+ < pre className = "bg-background" key = { 'sample-diagram' } >
120+ { `└─ samples <-- import this folder
121+ ├─ swoop
122+ │ ├─ swoopshort.wav
123+ │ ├─ swooplong.wav
124+ │ └─ swooptight.wav
125+ └─ smash
126+ ├─ smashhigh.wav
127+ ├─ smashlow.wav
128+ └─ smashmiddle.wav` }
129+ </ pre >
130+ < p >
131+ The name of a subfolder corresponds to the sound name under the “user” tab. Multiple samples within a
132+ subfolder are all labelled with the same name, but can be accessed using “.n( )” - remember sounds are
133+ zero-indexed and in alphabetical order!
134+ </ p >
135+ < p >
136+ For more information, and other ways to use your own sounds in strudel,{ ' ' }
137+ < a href = { `${ baseNoTrailing } /learn/samples/#from-disk-via-import-sounds` } target = "_blank" >
138+ check out the docs
139+ </ a >
140+ !
141+ </ p >
142+ < h3 > Preview Sounds</ h3 >
143+ < pre className = "bg-background" key = { 'sample-preview' } >
144+ n("0 1 2 3 4 5").s("sample-name")
145+ </ pre >
146+ < p >
147+ Paste the line above into the main editor to hear the uploaded folder. Remember to use the name of your
148+ sample as it appears under the "user" tab.
149+ </ p >
150+ </ div >
151+ ) : (
152+ ''
153+ ) }
154+ { ! soundEntries . length && soundsFilter !== 'importSounds'
155+ ? 'No custom sounds loaded in this pattern (yet).'
156+ : '' }
105157 </ div >
106158 </ div >
107159 ) ;
0 commit comments